C 使用一个递归调用进行快速排序
我们所有人都知道如何使用两个或多个递归调用编写快速排序 几天前,老师说用一个递归调用就可以实现。 实际上,我不知道如何用一个递归调用来保存O(n logn)C 使用一个递归调用进行快速排序,c,sorting,quicksort,C,Sorting,Quicksort,我们所有人都知道如何使用两个或多个递归调用编写快速排序 几天前,老师说用一个递归调用就可以实现。 实际上,我不知道如何用一个递归调用来保存O(n logn) 有什么想法吗 > P> C++快速排序,每次迭代一次递归调用,将栈开销减少到O(log(n))。还使用中位数3作为轴,并排除分区==轴的中间值 void QuickSort(int a[], size_t lo, size_t hi) { while(lo < hi){ size_t i = lo, j = (
有什么想法吗 > P> C++快速排序,每次迭代一次递归调用,将栈开销减少到O(log(n))。还使用中位数3作为轴,并排除分区==轴的中间值
void QuickSort(int a[], size_t lo, size_t hi) {
while(lo < hi){
size_t i = lo, j = (lo+hi)/2, k = hi;
int p;
if (a[k] < a[i]) // median of 3
std::swap(a[k], a[i]);
if (a[j] < a[i])
std::swap(a[j], a[i]);
if (a[k] < a[j])
std::swap(a[k], a[j]);
p = a[j];
i--; // Hoare partition
k++;
while (1) {
while (a[++i] < p);
while (a[--k] > p);
if (i >= k)
break;
std::swap(a[i], a[k]);
}
i = k++;
while(i > lo && a[i] == p) // exclude middle values == pivot
i--;
while(k < hi && a[k] == p)
k++;
// recurse on smaller part, loop on larger part
if((i - lo) <= (hi - k)){
QuickSort(a, lo, i);
lo = k;
} else {
QuickSort(a, k, hi);
hi = i;
}
}
}
void快速排序(int a[],大小低,大小高){
while(lop);
如果(i>=k)
打破
交换(a[i],a[k]);
}
i=k++;
而(i>lo&&a[i]==p)//排除中间值==pivot
我--;
而(k如果(i -LO)示例C++ + QuaseRead,每次迭代一次递归调用,将栈开销减少到O(log(n)),也使用3的中值作为枢轴,而不包括分区= =枢轴的中间值(< /P>)。
void QuickSort(int a[], size_t lo, size_t hi) {
while(lo < hi){
size_t i = lo, j = (lo+hi)/2, k = hi;
int p;
if (a[k] < a[i]) // median of 3
std::swap(a[k], a[i]);
if (a[j] < a[i])
std::swap(a[j], a[i]);
if (a[k] < a[j])
std::swap(a[k], a[j]);
p = a[j];
i--; // Hoare partition
k++;
while (1) {
while (a[++i] < p);
while (a[--k] > p);
if (i >= k)
break;
std::swap(a[i], a[k]);
}
i = k++;
while(i > lo && a[i] == p) // exclude middle values == pivot
i--;
while(k < hi && a[k] == p)
k++;
// recurse on smaller part, loop on larger part
if((i - lo) <= (hi - k)){
QuickSort(a, lo, i);
lo = k;
} else {
QuickSort(a, k, hi);
hi = i;
}
}
}
void快速排序(int a[],大小低,大小高){
while(lop);
如果(i>=k)
打破
交换(a[i],a[k]);
}
i=k++;
而(i>lo&&a[i]==p)//排除中间值==pivot
我--;
而(kif((i-lo)可以使两个递归调用中的一个成为tailcall,这可以消除(转化为迭代而不是递归)。这几乎就像使用一个循环来进行两个递归调用。不确定它有什么好处。尝试?为了避免最坏情况下的堆栈溢出,将使用循环和递归的组合。在进行分区后,对较小的部分使用递归,然后代码循环回以拆分较大的部分。使用此方法,最坏的CA堆栈空间是O(log2(n))。这里已经讨论过,还有流行的“loguy-higuy”实现:。只需在谷歌上搜索“qsort-loguy-higuy”,你就会发现很多。你可以使两个递归调用中的一个成为尾调用,这可以消除(变成迭代而不是递归)。这几乎就像使用一个循环来进行两个递归调用。不确定它有什么好处。尝试?为了避免最坏情况下的堆栈溢出,将使用循环和递归的组合。在进行分区后,对较小的部分使用递归,然后代码循环回以拆分较大的部分。使用此方法,最坏的CA堆栈空间是O(log2(n))。这里已经讨论过,还有流行的“loguy-higuy”实现:。只需在谷歌上搜索“qsort-loguy-higuy”你会发现很多这样的东西。从技术上来说,你还有两个calls@BasileStarynkevitch-每次迭代一次递归调用,以避免堆栈溢出,否则nephi12的链接将显示一个递归调用示例。@BasileStryneVitch,如果不是对较小的部分进行递归调用,而是默认为第一部分(与尺寸无关)您只得到一个递归调用…从技术上讲,循环是递归的另一种形式,这是执行其中一个递归调用的方式。对吗?列表中有两个调用,但在同一个调用中从来没有调用过这两个调用。@BasileStarynkevitch-我添加了一个仅使用一个递归调用的替代性代码片段。技术很遗憾,你还有两个递归函数calls@BasileStarynkevitch-每次迭代一次递归调用,以避免堆栈溢出,否则nephi12的链接将显示一个递归调用示例。@BasileStryneVitch,如果不是对较小的部分进行递归调用,而是默认为第一部分(与大小无关)您只得到一个递归调用…从技术上讲,循环是另一种递归形式,这是一种执行一个递归调用的方式。对吗?列表中有两个调用,但在同一个调用中从未同时调用过它们。@BasileStrynkevitch-我添加了一个仅使用一个递归调用的替代性代码片段。