gpt4 book ai didi

algorithm - 快速排序:迭代或递归

转载 作者:塔克拉玛干 更新时间:2023-11-03 05:22:22 25 4
gpt4 key购买 nike

我了解了快速排序以及如何在递归和迭代方法中实现它。
在迭代方法中:

  1. 将范围 (0...n) 压入堆栈
  2. 用一个枢轴对给定的数组进行分区
  3. 弹出顶部元素。
  4. 如果范围有多个元素,则将分区(索引范围)压入堆栈
  5. 执行以上3步,直到栈为空

递归版本是wiki中定义的普通版本。

我了解到递归算法总是比迭代算法慢。
那么,就时间复杂度(内存不是问题)而言,哪种方法更受欢迎?
哪一个速度足够快,可以用于编程竞赛?
C++ STL sort() 是否使用递归方法?

最佳答案

就(渐近)时间复杂度而言 - 它们是相同的。

“递归比迭代慢”——这句话背后的合理性是因为递归堆栈的开销(在调用之间保存和恢复环境)。
然而 - 这些是恒定数量的操作,同时不会改变“迭代”的数量。

递归和迭代快速排序都是O(nlogn) 平均情况O(n^2) 最坏情况.


编辑:

只是为了好玩,我用帖子附带的 (java) 代码运行了一个基准测试,然后我运行了 wilcoxon statistic test , 检查运行时间确实不同的概率是多少

结果可能是决定性的(P_VALUE=2.6e-34,https://en.wikipedia.org/wiki/P-value。请记住,P_VALUE 是 P(T >= t | H),其中 T 是检验统计量,H 是零假设)。但答案并不是你所期望的。
迭代求解平均408.86 ms,递归平均236.81 ms

(注意 - 我使用 Integer 而不是 int 作为 recursiveQsort() 的参数 - 否则递归会取得更好的效果,因为它不必装箱很多整数,这也很耗时 - 我这样做是因为迭代解决方案别无选择,只能这样做。

因此 - 您的假设不正确,递归解决方案(至少对于我的机器和 Java)比 P_VALUE=2.6e-34 的迭代解决方案更快。

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);
}

关于algorithm - 快速排序:迭代或递归,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28342182/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com