快速排序Quicksort怎么写即其原理(这里给出升序),后面有疑点总结,这段代码无需输入,可以直接复制去改变数据进行调试
#include<bits/stdc++.h> //这是本章所有代码,找不到可以来这里看看
using namespace std;
int a[101];
void Quicksort(int l,int r);
int Partsort(int l,int r);
int main(){
srand((unsigned int)time(NULL));
for(int i = 0;i<10;i++)a[i]=rand()%101;
cout<<"排序前的a数组序列:"<<endl;
for(int i = 0;i<10;i++)cout<<a[i]<<" ";
cout<<endl<<"排序后的序列:"<<endl;
int l = 0,r = 9;
Quicksort(l,r);
for(int i = 0;i<10;i++)cout<<a[i]<<" ";
return 0;
}
void Quicksort(int l,int r){ //这里l和r可以相等也可以不相等,因为 后面的Partsort会判断,如果r==l,程序直接出来了
if(l>r)return ;
int p = Partsort(l,r);
Quicksort(l,p-1);
Quicksort(p+1,r);
}
int Partsort(int l,int r){ // 下面问题会在末尾解答
int key = a[l],ki = l; //问题1,为什么是r不是,l,能不能是其他数
while(l<r){
while(l<r&&a[r]>=key)r--; //问题2,为什么是l<r,而不是l<=r
while(l<r&&a[l]<=key)l++; //问题3,l和r的顺序可以互换吗,怎么互换呢
//问题4,这种方法真的可以对一些特殊数据排序吗?会不会hack呢?如果我右边出现问题,左侧没有问题(l一直加到l=r)也可以吗?为什么呢?
swap(a[l],a[r]);
}
swap(a[ki],a[r]);
return r;
}
这里的快排分了两个部分,一个是Quicksort(整体排序)和Partsort(部分排序)
Quicksort的作用是选定一个元素为 标准值 以它为基准,小于它的在左侧,大于它的在右侧,等于它的对排序没有影响,不作为考虑(不理解为啥没影响可以先往下看),输入下列数据
5
3 2 1 2 5
我们可以以3为基准,初步排序为 2 2 1 3 5,然后我们再对3左边和右边分别再次进行相同操作(就是递归操作),直到所有元素排序完成
Partsort(部分排序)作用是对部分区间内进行排序,并且返回标准值所在下标值,Quicksort函数的排序功能就是通过Partsort函数实现的,然后再用Partsort函数返回盖标准值排序后在数组的下标,对函数进行递归
void Quicksort(int l,int r){ //这里l和r可以相等也可以不相等,因为 后面的Partsort会判断,如果r==l,程序直接出来了
if(l>r)return ;
int p = Partsort(l,r); //如果要排序的数组元素为3 2 1 2 5
Quicksort(l,p-1);
Quicksort(p+1,r);
}
如果要排序的数组元素为3 2 1 2 5
第一次排序后数组元素为 2 2 1 3 5,那么p就指向3的下标3(数组下标从0开始)然后再对3的左右区间分别排序(递归)Quicksort(1,p-1)和Quicksort(p+1,r);
1.Partsort如何实现对区间范围内排序,又返回排序后的下标值呢?
int Partsort(int l,int r){ // 下面问题会在末尾解答
int key = a[l],ki = l; //问题1,为什么是l不是r,能不能是其他数
while(l<r){
while(l<r&&a[r]>=key)r--; //问题2,为什么是l<r,而不是l<=r
while(l<r&&a[l]<=key)l++; //问题3,l和r的顺序可以互换吗,怎么互换呢
//问题4,会不会有特殊情况漏洞;如果我右边出现问题,左侧没有问题(l一直加到l=r)怎么确保左侧一定小于等于标准值,右侧一定大于等于标准值?为什么呢?
swap(a[l],a[r]); //交换函数
}
swap(a[ki],a[r]);
return r;
}
这次输入量为3 4 1 2 5
这里我们用key来存储标准值,ki指向标准值的初坐标(一开始key=3,ki=0)先进行
while(l<r&&a[r]>=key)r--;
这段代码会让r停止下标为3的位置(该位置对应的值2小于3)
随后进行
while(l<r&&a[l]<=key)l++;
会使l停在下标为1的位置(改位置对应的值5大于3)
然后用swap进行交换值排序,就变成了3 2 1 4 5
又因为(l<r)仍然成立,重新判断右侧
while(l<r&&a[r]>=key)r--;
直到又遇见小于标准值的数据或l=r了
此时3 2 1 4 5,key=3, ki=0, l=r=2, a[l]=a[r]=1;
那么
swap(a[ki],a[l]); //对数组下标ki和下标l互换
变成1 2 3 4 5 ,返回p = 2,此样例只不过恰好一次就完成排序,一般还需要对p的左右两侧分别用Quicksort()继续排序(递归)
void Quicksort(int l,int r){ //这里l和r可以相等也可以不相等,因为 后面的Partsort会判断,如果r==l,程序直接出来了
if(l>r)return ;
int p = Partsort(l,r); //如果要排序的数组元素为3 2 1 2 5
Quicksort(l,p-1);
Quicksort(p+1,r);
}
问题4:
中间过程不用考虑特殊值,我们来讨论在l=r时会怎么样
我们分为两种情况来讨论
1. 最后是l一直加到与r相等
先想明白一件事,为什么r不动了?因为a[r]<key标准值了,那么当l移动到r处,ki是在左侧,那么ki与r处互换(此处r=l),肯定换回一个小于标准值的值回到左侧
2. 最后是r一直减到与l相等,那不就说明没有问题吗。如果l停在这,是因为它没动,那么l指向下标为0,那么a[l]<=key;如果l停在这,是因为a[l]>key,那么进过互换(这也是为什么一定要右边r先移动,l先移动再停下说明r也遇到a[r]<key停下),a[l]仍然<key,互换到左侧一定是小于标准值的
410

被折叠的 条评论
为什么被折叠?



