排序算法专题:十八排序算法的前世今生,恩怨纠缠 - 算法与数据结构面试分享(二十四)

前几天花了些时间在整体排序算法专题,回顾了小我们接触过的所有排序算法。总结下来大概可以分为以下10种经典原型,说是原型是因为算法题总是在变的,但是万变不离其宗,我们总是能找得到原型的。

这篇文章不会展开来讲哈,但是我们会描叙下它们的基本思想。敢兴趣的同学可以浏览到最后,我们会有更多的资源哈。


一、 冒泡排序

冒泡排序的基本思想来源于生活,小鱼在水底冒泡,上升的水面的过程中变得越来越大。扫描待排序的数组一遍,我们发现当前的数比后面的数大,我们就交换它。最坏的情况就是两两交换。完成一趟扫描,我们会得到一个最大的元素,接下来再进行第二趟,第三趟扫描,我们会依次得到第二大,第三大的数。所以该算法中会有两个嵌套的循环。

一张图说明问题:

 

以上便是最原始的冒泡排序,我们在此基础上我们对它做优化哈。第一步优化是,我们不想连续的两个数交换,因为他们的交换可能不会直接影响结果,所以我们想固定第一个数,扫描后面的数的时候都和第一个去比,小于第一个的我们就交换,之后还是和第一个元素去比较。我们在第一趟中把第一个元素当做哨兵,而第二趟我们把第二个元素做哨兵。


其实以上的改良中,我们依旧在两两交换。我们能不能扫描完了找到了剩余n-1个数中最大的元素我们再交换呢?也就是说每一趟我们都最多只交换一次。这样的改良,我们就得到选择排序。

二、选择排序

基本思想上面已经讲到了哈,第一趟就是在N-1个数中找最大或最小的,与第一个元素交换。每次都选择最大(小)的元素。我们做N-1趟也就把N个数都选择出来了。


三、插入排序

插入排序的思想是,我们假设当前元素之前已经有序了,那我们从之前的第一个数开始往前扫描,如果该数组比之前的元素大,那我们就忽略它(假设升序哈),若小于之前的元素,那它应该在之前的某个位置存在,我们就边找位置边往后移动,此时注意不能覆盖后面的元素。


四、希尔排序

希尔排序是插入排序的一种改良。原始的插入排序是依次往后扫描对吧,我们这次想跳着来比,即减小递增量的方式。当增量为n/2时,我们会挑选 0-n/2, 1-n/2+1,等两两形成一组进行分别插入排序。接下来我们的增量变为n/4,此时我们的配对会越来越少,但是没一个队伍会越来越大,最终我们的增量为1,也就是对原来的数组做原始的插入排序了,大家想一想,此时基本上已经不用移动元素了对吧?

看图哈:


五、归并排序

思想很简单,假设我们把数组一份为2,每一半都排好序了,我们把两个排好序的数组做一个合并,这个问题就解决了哈。然后我们怎么解决规模是一半的数组排序呢,递归哈。

上图哈:


六、快速排序

快速排序的名字我很不喜欢,大家就把它当做很快的排序吧。首先我们想确定一个杠杆,我们不期望杠杆前后都排好序,但是我们一旦确保了杠杆前面的都比它小,后面的都比它大,我们就把阶级矛盾转化为内部矛盾了哈,我们能确保杠杆的位置在排序序的数组中一定是不会再变化了。假设这样的话,如果我们把每一个杠杆都找出来,那整个数组不就都排好序了吗?

在这个基础上,我们再把原来的数组一份为二,以杠杆为界哈。我们再递归就好了。


七、计数排序

这里是有限制条件的哈,排序的数的范围是预先知道的,而且不宜太大。我们准备一张签到表,让每个元素自己去登记,之后再扫描下签到表,我们把原来的元素拼接起来就好了。


八、堆排序

这里利用了堆的特性哈,最大堆中根最大,大于左子树,右子树。那我们就可以把根拿出来,然后在剩下的N-1个元素再构建堆就好了。这里涉及到了堆的调整哈,在这里就不再细讲了,大家可以浏览我的视频教程哈。


九、基数排序

假设我们有多位数字,我们先基于个位排序,然后十位排序,再百位,如果我们每次排序的算法都是稳定的,那我们就可以采用这样的方式去排序了。其实这也是计数排序的一种改良哈。


十、桶排序

计数排序的一种改良,我们不再让每个数在签到表里都能找到自己,但是我们准备了M个签到表,假设最大的元素与最小元素的差值是P,我们就可以将 Min - Min+P/M范围的数放到第一个桶,而 Min+P/M - Min+2P/M放到第二个桶里了,依次类推。接下来我们将每个桶内的元素再去排序,最后我们把桶从小到大给串起来,即得到了排好序的结果。

 

更多资源:


同时,也欢迎大家访问我们的视频教程哈。

排序算法专题精讲
BAT,MS, Google 经典面试算法题
数据结构与算法


猜你喜欢

转载自blog.csdn.net/gaoming201314/article/details/80068884