排序(三)冒泡排序与快速排序(C语言实现)

冒泡排序与快速排序都属于交换排序,其中冒泡排序也是十分的出名,实现起来也比较简便,下面一一介绍这两种排序。

1、冒泡排序

冒泡排序的意思就是将最大的数沉底,或者最小的数提到最前面来,之后再抛开这个数找次大或此次小的数进行循环,这个过程比较像泡泡从小变大的过程因此称作冒泡排序。

1bd6dcdf1d0e415e93037eec626b4d13.png

代码实现:

void BubbleSort(int* a, int n)
{
	assert(a);//断言判断
	for (int j = 0; j < n; j++)
	{
		int flag = 0;//用于提高循环效率,如果提前排序完成,则不用再继续进行比较
                     //置flag为1后便可跳出循环
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
				Swap(&a[i - 1], &a[i]);
			flag = 1;
		}
		if (flag == 0)
			break;
	}
}

2、快速排序

快速排序正如其名,效率非常的快,但是算法比较复杂,要求使用递归思想。

我们先来看单趟的排序过程:

首先要选定一个值为key(一般都选择数组最左端或最右端的值),让所有比key小的值在key左边,比key大的值在key右边(以下为升序思路)

41b8eea733e147cfb8cc6c4060d483dd.png

 这里取最左端的值为key,接下来就是先从右边开始依次遍历数组寻找比key小的数

01856a55fc774e0998eb50f994001b7c.png

 此时right所在下标的值比key大,则再从左边开始找比key大的数

8ec8f321820b47c68d61acbcc836a739.png

 交换left与right所对应的值

8788637b7c2b4f2da4b9d695b96ad996.png

 之后再重复以上步骤直到left与right相遇为止

e0a5c77a6338447dac03ce833565433a.png

最后将left所对应的值与key交换(如果选取左边为key一定要从右边开始找,这样可以保证left最后所在位置一定比key小或等于key)

ea07ccbe79394e0c93082e06c12564fa.png

这时整个数组被分为三个区间其所对应的下标分别是[begin,key-1]key[key+1,end],其中key所在位置不用再变化,而要分别对左右两个区间再进行单趟快速排序

左:

e0489b9325af42738818c01ed436100f.png

右:

764900fa93814947b14ea404c9a5cdb7.png

因为取的数据比较巧,也只花了一次就完成排序了,没有体验出一个递归的过程,不过我们可以思考如果这一次排完还是无序便又要拆分成左右区间继续排序,直到区间只剩一个数或者不存在为止。

那么用代码来实现一下:

void QuickSort(int* a, int begin, int end)
{
	//当区间只有一个值或不存在则不需要再处理
	if (begin >= end)
	{
		return;
	}
	int left = begin;
	int right = end;
	int key = left;

	while (left < right)
	{
		//右边先走,找小
		while (left < right && a[right] >= a[key])//这里是第一个判断条件是防止left不动,right一直向左走越界的情况
											   //第二个判断条件的等于号一定不能少,如果左右都与key相等会死循环
		{
			right--;
		}
		//左边再走,找大
		while (left < right && a[left] <= a[key])
		{
			left++;
		}
		Swap(&a[right], &a[left]);
	}
	Swap(&a[left], &a[key]);//key取左边,右边先走一定能保证结束循环后left所在位置的值比key小
	key = left;
	//[begin,key-1]key[key+1,end],此时需要让key左右区间分别有序
	QuickSort(a, begin, key - 1);
	QuickSort(a, key + 1, end);//递归思想
}

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

双葉Souyou

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

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

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

打赏作者

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

抵扣说明:

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

余额充值