快速排序的递归实现和非递归实现

一、快速排序的递归实现

快速排序的思想是每次找到一个元素的位置,再在以这个元素分隔的两个子范围中分别再各自确定一个元素的位置,子子范围也是如此操作,当某个子范围只有一个元素或者没有元素时,便不再做任何操作。这是一个递归过程,递归退出的边界就是子范围中不存在元素或者只存在一个元素。

基于这个思想,很容易便得到递归处理的程序框图:
在这里插入图片描述
代码:

#include <cstdio>

using namespace std;

static void quickSort(int array[],int low,int high){
    int l=low,h=high,tmp;
    if (l<h){
        tmp=array[l];
        while (l<h){
            while (array[h]>=tmp){
                h--;
                if(l == h){
                    goto complete;
                }
            }
            array[l]=array[h];

            while (array[l]<tmp){
                l++;
                if(l == h){
                    goto complete;
                }
            }
            array[h]=array[l];
        }

        complete:
        array[l]=tmp;
        //递归处理左右的序列
        quickSort(array,low,l-1);
        quickSort(array,h+1,high);
    }
}

int main() {
	//测试
    int a[8]={49,38,65,97,76,13,27,49};
    quickSort(a,0,7);
    for (int i = 0; i < 8; i++) {
        printf("%d ",a[i]);
    }
    return 0;
}

二、快速排序的非递归实现

上述递归实现的局限性可能在于:当数据量特别大时,可能会导致栈溢出(栈涨的速度为 log ⁡ 2 n \log_2n log2n,也可能是我多虑了,涨地其实挺慢的)。

为了解决上面可能出现的问题,我们可以将递归实现转换为非递归实现,我们知道任何递归的过程都可以转化为一个迭代的过程,而转化的关键在于如何使用迭代来模拟整个递归的处理。

观察上面的递归处理过程,我们可以看到:每一次排序函数的调用都会再次重新调用两次新的排序函数,然后系统会按照调用顺序一步一步地进行处理和返回,而调用排序函数的关键在于必须将排序的范围告诉函数。

这个过程很像一个排队处理的过程,于是我们可以使用队列进行递归的模拟,而队列中的信息存储要处理的范围即可。当队列不为空时,表示还有范围未处理;队列为空时,表示所有的范围都已经处理完毕,也即确定了所有元素的位置,完成了排序工作。

于是我们可以得到下面非递归处理的程序框图:
在这里插入图片描述
代码:

#include <cstdio>
#include <queue>

using namespace std;

struct Scope{
    int low,high;
};

static void quickSort2(int array[],int low,int high){
    queue<Scope> scopes;
    scopes.push({low,high});
    Scope sp;
    while (!scopes.empty()){
        sp = scopes.front();
        scopes.pop();
        int l=sp.low,h=sp.high,tmp;
        if (l<h){
            tmp=array[l];
            while (l<h){
                while (array[h]>=tmp){
                    h--;
                    if(l == h){
                        goto complete;
                    }
                }
                array[l]=array[h];

                while (array[l]<tmp){
                    l++;
                    if(l == h){
                        goto complete;
                    }
                }
                array[h]=array[l];
            }

            complete:
            array[l]=tmp;
            //将左右子序列加入待处理队列中
            scopes.push({sp.low,l-1});
            scopes.push({h+1,sp.high});
        }
    }
}

int main() {
	//测试
    int a[8]={49,38,65,97,76,13,27,49};
    quickSort2(a,0,7);
    for (int i = 0; i < 8; i++) {
        printf("%d ",a[i]);
    }
    return 0;
}
  • 3
    点赞
  • 23
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

_Kirito

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值