如何解决快速排序:迭代或递归
“递归慢于迭代” –该语句背后的原因是由于递归堆栈的开销(在两次调用之间保存和恢复环境)。 但是-这些是固定数量的操作,而不会更改“迭代”的数量。
递归和迭代快速排序都是O(nlogn)
普通情况 和O(n^2)
最坏情况 。
只是为了好玩,我运行了一个基准测试,并在文章中附加了(java)代码,然后运行了wilcoxon统计测试,以检查运行时间确实不同的概率是多少
结果是结论性的(P_VALUE = 2.6e-34,这意味着它们相同的概率是2.6 * 10 ^ -34-非常不可能)。但是答案不是您所期望的。 迭代解决方案的平均值为408.86 ms,而递归解决方案的平均值为236.81 ms
(注意-我使用了-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);
}
解决方法
我了解了快速排序以及如何在递归和迭代方法中实现它。
在迭代方法中:
- 将范围(0 … n)推入堆栈
- 用枢轴对给定数组进行分区
- 弹出顶部元素。
- 如果范围中有多个元素,则将分区(索引范围)压入堆栈
- 执行上述3个步骤,直到纸堆为空
递归版本是Wiki中定义的普通版本。
我了解到,递归算法总是比迭代算法慢。
那么,就时间复杂度而言(内存不是问题),哪种方法更可取?
哪一个足够快用于编程竞赛?
c ++ STL sort()是否使用递归方法?
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。