qmap按插入顺序排序_互联网公司面试中常见的排序算法

74779891909ec371f954d745756bdcf2.png

​排序算法在程序设计和公司面试中不可或缺。

排序算法的稳定性:在一个序列里,如果有若干值一样的记录,在经过排序算法排序后,这些相同值相对位置没有发生改变,那么该算法稳定,否则不稳定。

排序算法可分为:插入排序,交换排序,选择排序,归并排序和分配排序。

1插入排序

直接插入排序

插入排序:插入排序的思想就是在待排序列中,第一个位置假定有序,在后面的待排序列中,依次比较,插入到有序序列中,以此类推,直到无序序列数为0。

9f520470cd04c8c16cedb0e03b74a0ce.png

直接插入排序代码如下:

f64be6dd0ed06d223f6e9c93897d5b8a.png

平均时间复杂度为O(n2)。

希尔排序

希尔排序对直接插入排序进行了改进希尔排序是将待排序列分成若干组,对每个组进行直接插入排序,然后对整个序列直接插入排序。步骤如下:假设待排序列长度为n。

75ead9fc4f6abb87ece68fe534d3c25a.png

希尔排序并不稳定,性能优于插入排序,但不如快速排序,在问题规模中等时表现良好。希尔排序代码其实就是在直接插入排序上稍作改进,代码如下:

cf98e9ca37361af4bbbaa013ae0d438d.png

2交换排序

交换排序:交换排序我们在学习中用的比较多,在交换排序里我们介绍冒泡排序和快速排序算法。

冒泡排序

冒泡排序:对一个待排序列,我们按相邻元素两两比较,若第一个比第二个大,就交换,一直到最后一个元素,此时,最后一个元素为最大值,然后重复上述过程,直到序列有序。代码如下:

0c856b13985748c9710eca7fd9f4788a.png

快速排序

快速排序:快速排序是一个经典的算法,在面试或程序设计中经常被用到。它的思想是对一组待排序列,首先选一个阈值(通常为数组第一个元素),然后对此进行一次快速排序,即最终结果是阈值的左边都比阈值小,阈值的右边都比阈值大。然后对阈值的左右分别递归快速排序。一次快速排序我们用Partition函数实现。

17663113d385d02efe21d653725e4f26.png

e47fbf5a6ab8a335be17a3653d7b3737.png

代码实现如下:

8776c7074f78b2b53a98fdd20881ffc2.png

3选择排序

简单选择排序

选择排序:选择排序实际上是将待排序列分为无序区和有序区,在无序区经过比较,找到最小值,放到有序区,直到完全有序。简单选择排序代码如下:

f7749d07246f8a36c1359917566f60b0.png

对于选择排序,我们要重复的比较关键码的大小,因此在效率上并不高。为了提高效率,减少比较次数,我们使用堆排序

堆排序

堆排序也是一个难点,堆分为大根堆和小根堆,是一种完全二叉树,大根堆每个结点大于等于左右子结点,小根每个结点小于等于左右子结点。堆排序的思想是将待排序列调整成小根堆,此时堆顶为最大值,将堆顶与堆尾交换,剩下的数据再调整成堆,以此类推。

堆排序需要解决三个问题,(1)如何将无序序列调整成大根堆;(2)如何处理堆顶元素;(3)如何将剩余数据重新调整成大根堆。

(1)建堆的顺序是从最后一个分支结点开始进行堆调整。若二叉树最后一个结点为n,那么n/2就是最后一个分支结点。(这里用到了完全二叉树的性质),那么对n调整,要找出其左右子节点的最大值来与n比较,若结点n的值大,不变,否则调换。

(2)将堆顶元素与堆尾元素交换。

(3)剩余元素除了堆顶,其余地方都有序,因此再调用一次shift即可。

代码如下:(这里一定要注意边界条件,小编调Bug调了半天)

f597cdd7d43d08d3cd5526f0d359c497.png

4归并排序

归并排序:所谓归并,即将两个或两个以上有序序列合并成一个有序序列的过程。归并排序就是对归并的递归。这里要注意的是,归并算法需要额外的数组,因此空间复杂度为O(n),有了辅助空间,归并算法的时间性能就会大大改善。

二路归并排序

将两个有序序列合并成一个有序序列,称为二路合并。

42d776401f23e05f4e3fcd460711b0fb.png

归并排序要解决的主要问题是实现一次归并,要使用到额外的数组。首先解决如何合并两个有序序列,比较两个序列的第一个数,谁小取谁,一直循环,直到一个序列为空,让剩余的数接在后面。

7d602b994520569d1ccee77dd6d3c64b.png

f5b3927d567019ea52f61f1b83d436f5.png

5分配排序

上面介绍的排序都是根据键值进行比较来排序,分配排序不进行关键码的比较,而是将序列中的数据分配,然后再收集起来。

桶排序

即桶是按编号摆放,我们将数据按编号放到对应的桶里,那么这些数据就自然有序了,前提是桶要按顺序摆放。有关桶式排序的代码,会在后面的链表章节给出。

基数排序

基数排序是桶排序的改进,当排序为小数时,为了减少桶的数量,可以采用多键值排序。

5e70e627a1e18b78eb2773d43c0fd8db.png

基数排序适用于关键码较少的情况,效率比较高。

6各种排序算法比较

不稳定排序:希尔排序,快速排序,堆排序。

d3acf4b0bf82be78a8cb7ec6526e0aa7.png

本文主要参考数据结构相关资料和《剑指offer》,本文所有代码均为本人编写并经过测试,如有错误或问题,欢迎留言或私信指正。

633aebd801f28f268ed9d9e4933d2814.png
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值