十大经典排序算法小结(附源码和菜鸟版注释)

十大经典排序算法(动画演示)这篇博客的指导下,博主一点一点码出了十大排序算法,并写了菜鸟级注释源码戳这里,下面记录一下自己的总结,基本上是从注释搬来的。

排序算法主要分两类,一类是比较类排序,一类是非比较类排序。

一、比较类排序

如题,比较类排序算法和核心在于比较,只是比较的方法不一样,主要有

  • 交换排序:即通过数与数之间地交换

如冒泡排序和快速排序。
冒泡排序:通过相邻两个数之间的比较,交换两个数的位置使之满足统一的规律(比如左边始终比右边小),不断将最大/小数“冒”出来放在顶端;
快速排序:还是通过不断交换,使得选中的基准数交换到属于它的位置(即左边全部小于或大于它,右边反之),然后固定不动,对左右两边的数重复这一操作,直到所有的数都固定不动。使用的是分治法,其实思路很简单,假设基准是左边第一个数,左边全是小于基准的数,操作就是把左边出现的大于基准的数与右边出现的小于基准的数对调位置,最后把最后一个小于基准的数和基准对调位置即可,然后对左右两边重复操作。

  • 插入排序:顾名思义,通过不断将数据插入到数组中的排序。

简单插入排序:依次选定数据向前(向数组首端)插入到合适的位置后重复操作,直到最后一个数。
希尔排序:听名字挺高级的,不过就是加了增量数列而已啦。根据增量划分为几个组,然后在同一个组中进行插入排序。比简单插入排序“聪明”一点的地方就是不再是一个一个去比较,而是分组插入排序

  • 选择排序:不断选择出最大/小数,将其置于顶端

简单选择排序:选择操作,即将当前无序数组中最大/小值的下标找出来,然后与无序区的第一个元素交换位置,那么这个元素就算是加入到与之相邻的有序区啦,反复操作。虽然冒泡排序也是选最大/小值,但还是不同的,这里是选下标就好了,找最大/小值的过程中没有发生交换,而冒泡排序选最大/小值是一路交换过去的。所以相比而言,冒泡排序还要稍微“聪明一点”,因为最佳情况下冒泡的时间复杂度为O(n),即数组为一个有序数组,而简单排序需要O(n^2),因此被称为最稳(sha)定(*)的算法之一。
堆排序:借助了堆的属性,稍微麻烦一点,但是思路也很简单,就是不断将堆顶元素和叶子节点的值做交换,只要记得每次交换之后检查新的数组是否满足堆的属性就好了。

  • 归并排序

归并排序:采用的也是分治法,先分完再合并,这里的分完指左右两支都出现了,记得分到一个元素的时候要返回这个元素,否则就是个死循环。合并的思路比较简单,两个待合并的数组元素中谁小先push谁,反之也可以。

二、 非比较排序

非比较排序理解起来就是按顺序收集数据。这个顺序是由所谓的“桶”决定的。简单理解来说就是画个数轴,然后把数轴上的点和待排序的数组元素关联起来,再按数轴的顺序输出就可以了。

  • 计数排序

最基本的非比较排序,数轴长度为最大值 - 最小值,然后把每个元素值xbucket[i]一一对应,如果有多个数,说明这些数都是相等的,记录一下一共有多少个数就可以了。那么索引i与元素值x一一对应,bucket[i]就是x出现的次数,然后按照索引的顺序输出就可以了。

  • 桶排序

改进的计数排序,改进点在于不再是一一对应(太浪费空间了),而是一个区间一个区间地对应,比如[10,19]这个区间的数都放在bucket[1]这个桶里面,1表示桶的索引,注意是放在桶里面,即此时的桶bucket[i]是一个容器,比如array,或者vector什么的。

  • 基数排序

改进的计数排序,改进点是我一位一位地比较,这里的位表示个位、十位、百位,当然是先低位比较再高位比较,这样最后结果才是高位优先嘛。所以这里的桶只要10个,存储0~9就好啦,比较完一次之后覆盖原数组进行比较下一位。

怕太小看不见,大一点儿~ 源码戳这里

发布了96 篇原创文章 · 获赞 19 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Thera_qing/article/details/102961708