C语言 史上最详细快速排序图解,让小白也能轻松理解

快速排序可以看作是冒泡排序的一种升级版,优点就是快速,但是稳定性差。
因为是史上最详细快速排序,所以我写的非常细~~基本每一句代码都解释+图解到位了,需要耐心浏览。
快速排序的功能概括就是在数组中选定一个key值,把小于key的数放在左边,大于key的数放到右边,再对key左边和右边的数分别再选一个key值进行重复操作

先上代码,再对代码进行图解,大家也可以先把代码跑一遍,有个底…

//快速排序
void my_sort(int arr[],int low,int high)
{
	//递归结束条件
	if (low >= high)
		return;

	//记录数组第一个值和最后一个值
	int left = low, right = high;
	//这里我们把第一个数选作中心值
	int key = arr[left];

	while (left < right)
	{
		while (left < right && arr[right] >= key)
		{
			right--;
		}
		arr[left] = arr[right];
		while (left < right && arr[left] <= key)
		{
			left++;
		}
		arr[right] = arr[left];
	}

	arr[right] = key;
	my_sort(arr, low, left - 1);
	my_sort(arr, left + 1, high);
}

int main(int argc, char *argv[])
{
	int arr[10] = { 2,8,6,1,4,3,9,0,7,5 };
	int len = sizeof(arr) / sizeof(arr[0]);
	
	my_sort(arr, 0, len-1);
	for (int i = 0; i < 10; i++)
	{
		cout << arr[i] << " ";
	}
	cout << endl;
	system("pause");
	return 0;
}

代码很少,但是得理解到位
函数三个参数void my_sort(int arr[],int low,int high)
//int arr[] 数组首地址
//int low 数组第一个元素位置
//int hight 数组最后一个元素位置
回溯上面代码

第一步
记录数组第一个位置(low)和最后一个位置(high)。
int left = low, right = high;
在这里插入图片描述
第二步
选取一个值作为中心值,保存在key中,这里我们选第一个值
int key = arr[left];
在这里插入图片描述
此时我们可以看作数组的第一个位置是空出来的(第一个位置的值已经保存到key中了,不用慌~),等待一个从右边数起小于key的值填到第一个位置来。
在这里插入图片描述
第三步
从最右边right开始找,找一个小于key的数,找到了便填到空出的位置上(即是left目前所以在的位置),如果找不到说明右边所有的数都比key大,则跳出循环,写代码,当left<right而且arr[right] >= key时,right一直往左边移动

while (left < right && arr[right] >= key)
{
	right--;
}
arr[left] = arr[right];

显然从right开始找起,5和7都比2大,当right移动这个0位置上,while (left < right && arr[right] >= key)这个条件不满足了,于是跳出循环,执行arr[left] = arr[right];如图,把0拷贝到了第一个位置
在这里插入图片描述
此时数组时这个样子的
在这里插入图片描述
那么接下来该做什么呢,现在我们知道右边right位置上空出来了,所以我们需要从左边找起,
第四步
从left开始找第一个大于key的数,填到右边去,于是写出代码,当left<right而且arr[left]<=key时,left一直往右移动。

while (left < right && arr[left] <= key)
{
	left++;
}
arr[right] = arr[left];

从右边找起,第一个位置上的数已经变成了0,小于key(2),left++,当left移动到8位置上,发现大于key(2),所以while (left < right && arr[left] <= key)条件不满足了 ,跳出循环执行arr[right] = arr[left];如图所示
在这里插入图片描述
此时数组变成这样
在这里插入图片描述
左边又空出来,所以大家应该知道又得从右边right当前位置接着开始找一个小于key(2)的数填到左边空出来的位置上,所有是重复上面的第三步,当第三步中把左边的数拷贝到右边时,又得重复第四步,于是有
第五步
我们把第三步和第四步的代码再用一个whille循环包起来就有如下代码

while (left < right)
{
	while (left < right && arr[right] >= key)
	{
		right--;
	}
	arr[left] = arr[right];
	while (left < right && arr[left] <= key)
	{
		left++;
	}
	arr[right] = arr[left];
}

可能有人会想为什么while中的条件是left < right,因为left是从左边最小的位置开始遍历,right是从右边最大的位置开始遍历,当left=right时,说明找到了同一个数了,已经把所有的数都对比过了,所以此时循环结束。
好了,再结合第一步和第二步,我们的代码就写到这了

void my_sort(int arr[],int low,int high)
{
	//第一步
	int left = low, right = high;
	//第二步
	int key = arr[left];

	//第五步
	while (left < right)
	{
		//第三步
		while (left < right && arr[right] >= key)
		{
			right--;
		}
		arr[left] = arr[right];
		//第四步
		while (left < right && arr[left] <= key)
		{
			left++;
		}
		arr[right] = arr[left];
	}
}

于是在第五步循环中再执行第三步的操作,从right开始找到1的位置是小于key的

在这里插入图片描述
数组变成这样
在这里插入图片描述
右边又空出来了,执行第四步找到6是大于key的,则有
在这里插入图片描述
数组变成
在这里插入图片描述
此时所有的数都已经遍历完了,再移动一次left和right便会相等,我们就不需要再比较了,就有为什么上面while循环的结束条件是left<right,所以当跳出循环时则表示,left=right

现在发现还有一个位置是空出来的 ,于是我们得把这个位置再填上,
那么用哪个值填呢,没错,就是最开始拿出来的中心值key,你会发现这个位置左边的值都小于key,右边的值都大于key,这也是写这个代码的目的,于是有
第六步

arr[right] = key;//也可写成arr[left] = key;因为此时left和right是相等的

这样我们的第一轮排序便完成了,数组此时的排序是这样的
在这里插入图片描述
第七步
最后便是完成递归操作

my_sort(arr, low, left - 1);
my_sort(arr, left + 1, high);

对上一个中心值的两边再进行第一步到第七步的重复动作,我们把0 1扔到my_sort里面再排序一便,把6 4 3 9 8 7 5仍到my_sort里面也排序一遍,重复这个操作,这个便是递归,如果有同学对递归有疑问的,可以留言,我再写一篇史上最详细递归解析~
如图
在这里插入图片描述
于是整套代码解释完毕,最后补上前两行的递归结束条件,写递归函数一定要注意写结束条件,否则陷入死循环了,已经看到这的同学,至于递归条件为什么是low >= high,相信大家应该没问题了吧。

void my_sort(int arr[],int low,int high)
{
	//递归结束条件
	if (low >= high)
		return;

	//第一步
	int left = low, right = high;
	//第二步
	int key = arr[left];

	//第五步
	while (left < right)
	{
		//第三步
		while (left < right && arr[right] >= key)
		{
			right--;
		}
		arr[left] = arr[right];
		//第四步
		while (left < right && arr[left] <= key)
		{
			left++;
		}
		arr[right] = arr[left];
	}
	//第六步
	arr[right] = key;//也可写成arr[left] = key;因为此时left和right是相等的
	//第七步
	my_sort(arr, low, left - 1);
	my_sort(arr, left + 1, high);
}

最后大家如果看懂了的话,回顾上面第三步和第四步的图中,我所画的空出来的位置,并不是那个位置上的数真的被清空了,而是为了方便让大家理解,数组上的数还是存在的,只是我们要往那个位置上填一个比key值大或者比key值小的数。

如有疑问,欢迎大家踊跃留言,最后点一个赞呗~

  • 123
    点赞
  • 287
    收藏
    觉得还不错? 一键收藏
  • 27
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值