(漸近的な)時間計算量に関しては、どちらも同じです。
「再帰は反復よりも遅い」-このステートメントの背後にある理論的根拠は、再帰スタックのオーバーヘッド(呼び出し間の環境の保存と復元)によるものです。
ただし、これらは一定の操作数ですが、「反復」の数は変更されません。
再帰的および反復的なクイックソートはどちらも、O(nlogn)
平均的なケースとO(n^2)
最悪のケースです。
編集:
楽しみのために、投稿に(java)コードを添付してベンチマークを実行し、次にwilcoxon統計テストを実行して、実行時間が実際に異なる確率を確認しました。
結果は決定的なものになる可能性があります(P_VALUE = 2.6e-34、https: //en.wikipedia.org/wiki/P-value。P_VALUEはP(T> = t | H)であることに注意してください。ここで、Tはテスト統計であり、 Hは帰無仮説です)。しかし、答えはあなたが期待したものではありません。
反復解の平均は408.86ミリ秒でしたが、再帰解の平均は236.81ミリ秒でした。
(注-私は引数としてInteger
ではなく使用しました-そうでなければ、再帰ははるかに良く達成されたでしょう、なぜならそれは多くの整数をボックス化する必要がないので、これも時間がかかります-反復解は選択の余地がないので私はそれをしましたがそうする。int
recursiveQsort()
したがって、-あなたの仮定は真実ではありません。再帰的な解決策は、P_VALUE = 2.6e-34の反復的な解決策よりも高速です(私のマシンとJavaの場合は少なくとも)。
public static void recursiveQsort(int[] arr,Integer start, Integer end) {
if (end - start < 2) return; //stop clause
int p = start + ((end-start)/2);
p = partition(arr,p,start,end);
recursiveQsort(arr, start, p);
recursiveQsort(arr, p+1, end);
}
public static void iterativeQsort(int[] arr) {
Stack<Integer> stack = new Stack<Integer>();
stack.push(0);
stack.push(arr.length);
while (!stack.isEmpty()) {
int end = stack.pop();
int start = stack.pop();
if (end - start < 2) continue;
int p = start + ((end-start)/2);
p = partition(arr,p,start,end);
stack.push(p+1);
stack.push(end);
stack.push(start);
stack.push(p);
}
}
private static int partition(int[] arr, int p, int start, int end) {
int l = start;
int h = end - 2;
int piv = arr[p];
swap(arr,p,end-1);
while (l < h) {
if (arr[l] < piv) {
l++;
} else if (arr[h] >= piv) {
h--;
} else {
swap(arr,l,h);
}
}
int idx = h;
if (arr[h] < piv) idx++;
swap(arr,end-1,idx);
return idx;
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
public static void main(String... args) throws Exception {
Random r = new Random(1);
int SIZE = 1000000;
int N = 100;
int[] arr = new int[SIZE];
int[] millisRecursive = new int[N];
int[] millisIterative = new int[N];
for (int t = 0; t < N; t++) {
for (int i = 0; i < SIZE; i++) {
arr[i] = r.nextInt(SIZE);
}
int[] tempArr = Arrays.copyOf(arr, arr.length);
long start = System.currentTimeMillis();
iterativeQsort(tempArr);
millisIterative[t] = (int)(System.currentTimeMillis()-start);
tempArr = Arrays.copyOf(arr, arr.length);
start = System.currentTimeMillis();
recursvieQsort(tempArr,0,arr.length);
millisRecursive[t] = (int)(System.currentTimeMillis()-start);
}
int sum = 0;
for (int x : millisRecursive) {
System.out.println(x);
sum += x;
}
System.out.println("end of recursive. AVG = " + ((double)sum)/millisRecursive.length);
sum = 0;
for (int x : millisIterative) {
System.out.println(x);
sum += x;
}
System.out.println("end of iterative. AVG = " + ((double)sum)/millisIterative.length);
}