快速排序Quicksort怎么写即其原理

快速排序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,互换到左侧一定是小于标准值的

问题3:可以互换,只不过要先l++再r–;

问题2:我们要找的是l=r时的点,将此点与数组里ki的位置互换,而当如果把l<r改成l<=r,可能会使l>r成立

问题1:理论上可以,但是你又不知道有部分排序的区间长度,而用l好r肯定没问题

(可能这里问题分析啥的有点啰嗦和冗长,实际上代码结构很清晰,直接看代码也可以看懂)

评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值