(C++)排序——四种排序算法与STL sort()使用详解

冒泡排序

冒泡排序是排序原理最简单的一种排序. 在运算规模较小时非常实用,其思想也能辅助解决某些更复杂的问题.

冒泡排序(bubble sort)的思想如下:

例如,我们进行升序排序,那么,从长度为n的数组的第0位开始,将其依次与后一位比较,如果前一位大于后一位,那么就交换这两个元素. 从0开始交换到最后一个后,一次排序完成. 现在,我们已经将我们需要的有序数组排好一位了:最大的数现在被放在了数组最后面. 那么,未排序的部分长度只有n-1了.
再次排序,次大的数已经放在了整个数组的倒数第二位.

然后,我们不断重复这个过程,缩小未排序数组的长度,直到未排序数组长度为1,冒泡排序的程序就走完了.

例如,我们给一个数组:7,8,10,2,4,3,它们的位置对应下标0,1,2,3,4,5.

第一次排序,从下标为0的7开始,不交换7和8,不交换8和10,交换10和2,交换10和4,交换10和3.
第一次排序结束后,数组变为7,8,2,4,3,10.(访问的下标从0到4)
同样地,第二次排序,得到7,2,4,3,8,10.(从0到3)
然后是:
2,4,3,7,8,10;(从0到2)
2,3,4,7,8,10.(从0到1)
2,3,4,7,8,10.(只有0)(虽然已经排好序,但是按冒泡排序的程序走还得检查一次)

每次排序,未排序的数组中最大的元素总是被留在了最后面. 我们需要排的这个最大数在一次一次的交换中像泡泡一样咕噜咕噜地跑到了最后面,就像“冒泡”一样,因此,我们把这种排序称作冒泡排序——bubble sort.
要实现冒泡排序,我们需要2层循环,一层循环的长度就是数组的长度减去1——我们的未排序数组长度应从n逐步减至1,需要做n-1次操作. 二层循环的长度则是每个未排序数组的长度——从n直到1.

升序的冒泡排序的实现代码如下:

void bubble_sort(int a[]int n)//参数分别是数组和数组长度
{
   
	for(int i = 0; i < n - 1; ++i)
		for(int j = 0; j < n - 1 - i; ++j)
		{
   
			if(a[j] > a[j + 1])
			{
   
				int tmp = a[j];
				a[j] = a[j + 1];
				a[j + 1] = tmp;
			}
		}
}

至于降序,只需要变if中的大于号为小于号就可以了.

另外,选择排序也是一种常用的排序方法,和插入排序的执行方式十分相似. 它是从未排序数组中选择最小的数排在最前面,然后再从剩下未排序的数中选择最小的排在之前最前面的数的后面,直到排完.

插入排序

冒泡排序很好地解决了简单的排序问题. 但,我们不得不审视它的运行效率:例如上例在排4次后,已经形成了有序序列,冒泡排序会进行一次多于的判断循环,这就造成了程序对时间资源的浪费.

由于冒泡排序需要进行2层循环,我们可以知道,它的时间复杂度应为O(n2). 实际上,当我们需要排序一个非常大的数组时,冒泡排序极大可能会重复判断相当多的数对. 当数组的长度大于106时,程序平均运行时间很可能会超过10秒!这在许多编程竞赛和实际问题解决中是绝对不允许的. 于是,在此基础上,我们提出插入排序,相较于冒泡排序,它可以有效避免重复判断.

插入排序的思想是:先假设数组第一个元素已经排好序,然后将后面的数依次插入这个有序数表. 例如,再次考虑数组7,8,10,2,4,3. 一开始,7已经排好序,我们从8开始,它应该插入7的后面,然后考虑10,它应该插在8的后面,这样,有序组是7,8,10. 再轮到2,由于它比10,8,7都小,它应该插在7的前面,得到数组2,7,8,10,4,3. 再次重复操作,依次得到2,3,7,8,10,4、2,3,4,7,8,10. 这样,我们就完成了这次排序.

它比冒泡优秀在哪?

我们发现,如果这个数组的某些部分原本就是有序的,插入排序就会避免重复判断大小关系,继续插入后一个数,而冒泡排序不管数组如何排列,总是对每两个数多次比较. 当数组原本有序时,插入排序只需要依次把数插进来即可,这个时候它的时间复杂度是O(n).

但面对完全逆序数组,插入排序让每个数找到位置时,需要从有序组的后面往前面一直寻找位置,需要耗费和冒泡排序一样多的操作.

因此,我们说,插入排序的时间复杂度是O(n)~O(n2),与输入数据的特点有关.

下面是插入排序的实现代码:

void insert_sort(int a[] , int len)//插入排序
{
   
    /*1.从第一个元素开始,该元素可以认为已被排序;
    2.取出下一个元素,在已经排序的元素序列中从后向前扫描;
    3.如果该元素(已排序)大于新元素,将该元素移到下一个位置;
    4.重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;
    5.将新元素插入到该位置后,重复2~5*/
    int b[len] = {
   0};
    b[
  • 2
    点赞
  • 11
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值