C 使用一个递归调用进行快速排序

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 = (

我们所有人都知道如何使用两个或多个递归调用编写快速排序

几天前,老师说用一个递归调用就可以实现。 实际上,我不知道如何用一个递归调用来保存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 = (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-我添加了一个仅使用一个递归调用的替代性代码片段。