考研八大排序(除了归并排序版)

八大排序

1.快速排序:

挖坑法,先把第一个数放入监控哨中(也就是挖坑),从右边查找比监控哨小的数,放入第一个数的位置(也就是填坑),再从左边查找比监控哨大的数,放入上一个数的位置,左右逼近,以此类推。最后low=high,再把监控哨给该位置填上,画上了句号。

但这只是确定了分治点,分支点左右两边还需要利用递归完成一样的操作。

2.冒泡排序:

最简单复杂度最高的排序。

先确定一共有n个数,每一轮都需要把一个数从数组底部冒泡于数组头部,那么最多需要冒泡n-1次,这里我们可以进行一次选择判断,当存在一轮冒泡不交换位置,则可以判定排序已经排好了。第一轮冒泡需要比较n-1次,第二轮需要比较n-2,…依次类推,由此可见每一轮比较的次数是在变化的,即比较的中止条件在变化。

for(int j=n-1;j>i;--j )若i是头部即每轮冒泡都要以i为结束条件。

3.选择排序:

简单并且好用的排序,比较次数比快排复杂,有能力还是选择快排比较好叭。

比较简单直接上代码了,原理就是从第一个数依次往后比较,然后把最小的值与第一个数进行交换,这样一轮就确定了第一个数是最小值,依次往后操作,一共也最多移动n-1次

for(int i= 1;i < n-1; ++i)

{

 int min = i;

for(int j = i + 1; j < n ; ++j)

if(a[min]>a[j])

{

min = j;

}

}

if(min!=i)

{

swap(a[i],a[min]);

}

4.插入排序

可以利用哨兵作为中止移动位置的条件,当进行从小大排序时,对某个位置监控哨兵时,大于哨兵的值全部往后移动,必会空出一个位置让放入监控哨的值填坑。如果不加以判断的话,一共需要监控n-1个 位置,每一轮最多需要移动1,2,3,…n-1可见,循环的复杂度还是O(n^2)

5.折半排序

顾名思义,每次都会折半,但是这个折半只是查找待插入位置的折半,并非排序移动位置次数的折半。

第一轮,监控哨放入的是第一个位置的值

我们会用low=1来记录查找的起始位置,high=i-1来记录查找的结束位置。,mid=(low+high)/2作为确定待插入位置的判断条件,若a[mid]>a[0],说明待插入的值在mid的左边,high=mid-1;若a[mid]<a[0],说明待插入的值在mid的右边,low=mid+1;

当low=high时,判断出high后面的位置=high+1作为判断移动的中止条件。与插入排序相比 ,移动的次数是减少了,不过减少的不明显。

6.希尔排序  

有点复杂,不稳定,数量较少时移动次数可能变多,但是数量庞大时性能就会显示出来。

for(int dk= dk/2;dk>=1;dk/=2)

//这里dk表示步长

for(int i =2+dk ;i<n;++i)

{

if(a[i]<a[i-dk])

{

a[0]=a[i];

for(int j =i-dk; j>0 && a[j]>a[0]; j-=dk)

{

a[j+dk] = a[j];

}  

a[j+dk] = a[0];

}

}

仔细会发现,shell’s排序与插入排序的区别只是多了一个步长。

7.堆排序

利用了满二叉树的思想去构造的数组排序。

本质上还是数组,只不过“心中一棵树,树在我们心中”。

堆排首先确定的是dad=start=0,son=dad*2+1,这里的dad认为是父节点,son认为是左右子树。

所以先假设maxheapsort函数,我们先进行从0到底的排序

先判断左右子树是否存在并且比较大小。再判断儿子是不是比父亲大,是的话交换位置,不是则退出循环,认定形成了大顶堆。

当大顶堆形成之后,一般是层次遍历为从大到小。

那么 现在将堆底和堆顶交换位置,这样认定为确定了最大值的位置(原本最大值的位置是堆顶,现在是堆底),那么下次排序只需要排序n-1个数,依次类推,进行循环上面的maxheapsort函数,那么可以将数组排序成层次遍历为从小到大的数组。

不难看出,堆排序比较复杂,一般不会使用。

 

 

 

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值