C++快速排序方法

#include <vector>
#include <iostream>

using namespace std;

/*快速排序的思路是:
 定一个base基准点比如a[0]位置的值,然后在序列头和序列尾巴分别放一个路标,分别从尾到头和从左到右遍历,分别把大于base值的值和小于base值的值放在base值的右边和左边
 然后在通过递归的方式对左边和右边进行处理。*/
void QuickSort(vector<int> &a, int low, int high)//必须传引用,否则出错,因为vector是一个类对象
{
    if( low > high)/*这里需要做判断。目的是防止前后过度遍历*/
        return;
    
    int l = low;/*一个左指针从左往右遍历,一旦遇得大于base值的元素停止遍历*/
    int r = high;/*一个右指针从尾往左遍历,一旦遇到小雨base的元素停止遍历等待数据交换*/
    int base= a[low];//记录base值

    while (l < r)/*最大让两个指针碰到,不能超过分界线遍历*/
    {
        /*如果遍历的数据本身大于base值,则继续遍历,否则遇到的是小于base值的,此时循环停止,继续遍历前半部分
         特别注意的是:一定要先d扫面后面部分,在扫描前半部分,不能把顺序反了。*/
        while (a[r] >= base&& l < r) /*这一定要>=,不能忘记=*/
            r--;
        /*退出循环则说明在尾巴上找到了小于Base的值*/
        
        /*如果遍历的数据本身小于base值,则继续遍历,否则遇到的是大于base值的,此时循环停止*/
        while (a[l] <= base && l < r)/*这一定要<=,不能忘记=*/
            l++;
        /*退出循环则说明在前半部分上找到了大于Base的值*/
        
        /*交换找到的这两个值的位置关系*/
        swap(a[l],a[r]);
        /*这一轮结束,然后在l<r过程中继续遍历下一轮找到左右两边所有的小于大于base的值,并且放在base的左边部分和右边部分*/
    }
    /*运行到这里则说明l和r碰头(也就是l一定等于r)了,则退出遍历,此时l对应的元素一定是小于base值的,因此此时将这个l对应的数据和base值(a[low])交换位置
     此时就把这个数列以base为基准值,左边放的是小于base的值,右边放的是大于Base的值,然后在对左右两边进行递归最终就可以把序列转换成
     一个有序序列*/
    swap(a[low], a[l]);

    QuickSort(a, low, l-1);
    QuickSort(a, r + 1, high);/*这里写成l+1也行的*/
}


int main()
{
    vector<int > a;
    a.push_back(5);
    a.push_back(4);
    a.push_back(8);
    a.push_back(2);
    a.push_back(7);
    a.push_back(9);
    a.push_back(3);
    a.push_back(1);
    
    for(auto &t:a){
        cout<<t<<" ";
    }
    cout<<endl;
    
    QuickSort(a, 0, a.size()-1);
    for(auto &t:a){
        cout<<t<<" ";
    }
    cout<<endl; 
}
/*还有一种方法就是不选择数组的第一个数为哨兵数,而是任意选择一个值。此时就不需要要求遍历是需要冲尾巴开始了,而是可以从左到右也可以从右到左,任意开始遍历。但是有一个地方需要注意的就是递归时候的区间,需要按照0-->r和l->end的方式,而不是0->l-1和l+1->r的方式,这里需要注意。*/
void QuickSort(vector<int> &nums, int start, int end){
    if(start >= end){ /*因为有递归运算,所以需要有退出条件*/
        return ;
    }
    int l = start;
    int r = end;
    int key =nums[start];/*任意找一个点点的数据,可以是任意的点,这里随便写了一个start点*/

    while(l<r){/*从头开始遍历,从左到右找到比keyd大的数据停下,从右找比key小的数据,然后两个交换位置。*/
        while(nums[l] < key&& l<=r){/*从左到右找大于key的数据*/
            l++;
        }
        while(nums[r] > key&& l<=r){/*从右到d左找小于key的数据*/
            r--;
        }
        
        /*找到则交换,但需要实在左边小于等于右边的情况下才交换,同时交换后为了继续找下一对,s需要l和r继续增加和减少*/
        if(l <= r){/*最终交汇处就是等于,所以需要等于*/
            swap(nums[r],nums[l]);
            l++;/*这里要继续增加或者减少*/
            r--;/*这里要继续增加或者减少*/
        }
    }
    /*注意走到这里r和l不一定相等,而且还存在r在l的左边,甚至r=-1的可能*/
    QuickSort(nums,start,r); /*这里为什么不是l-1和l+1*/
    QuickSort(nums,l,end);
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值