写在前面:
本篇博客主要总结一下经典的十大排序算法。
简单的、整天接触的排序算法,就只用动图来表示一下思想就好,难的,比较陌生的,会一步一步列出思路。不贴详细代码,但是有非常详细的思路,保证看懂。
┗|`0′|┛
工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。*
举个栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
工作原理:重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。
一样的栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
工作原理:通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
一样的栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
工作原理:1959年Shell发明,第一个突破O(n 2)的排序算法,是简单插入排序的改进版。它与插入排序的不同之处在于,它会优先比较距离较远的元素。使得数移动时能跨过多个元素,则进行一次比较就可能消除多个元素交换。希尔排序又叫缩小增量排序。
希尔排序步骤描述:
1.选择一个增量k,一般取序列的一半为增量。
2.将整个待排序的序列,分割成为k个组,然后分别对每组进行插入排序
3.增量减半,重复步骤2、3,直到增量为1。
4.当增量因子为 1 时,整个序列作为一个组来进行插入排序,组长度即为整个序列的长度。
<( ̄ˇ ̄)/
那么到底应该怎样分割k个序列?
据优先比较距离较远元素原则,讲一个简单的记忆方法,增量k是多少,就隔几个,标记这些元素,然后将这些元素分为一组
动图演示:
归并排序是建立在归并操作上的一种有效的排序算法。该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为2-路归并。
之前的栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
基本思想:通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。
1.从数列中挑出一个元素,称为基准。
2.重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作;
3.递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序。
之前的栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
当然。。。快排的话。 sort() 函数了解一下。
~( ̄▽ ̄~)(~ ̄▽ ̄)~
堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
基本概念:堆排序(英语:Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。
每个结点的值都大于或等于其左右孩子结点的值,称为大顶堆;或者每个结点的值都小于或等于其左右孩子结点的值,称为小顶堆。
补充一下完全二叉树的概念:除了最后一层之外的其他每一层都被完全填充,并且所有结点都保持向左对齐。
堆排基本步骤:
1.将无序序列构建成一个堆,根据升序降序需求选择大顶堆或小顶堆;
2.将堆顶元素与末尾元素交换,将最大元素"沉"到数组末端;
3.重新调整结构,使其满足堆定义,然后继续交换堆顶元素与当前末尾元素,反复执行调整+交换步骤,直到整个序列有序。
这两种排序很像,基本思想都是一样的,所以放在一起说。 (o゜▽゜)o☆
计数排序不是基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中。 作为一种线性时间复杂度的排序,计数排序要求输入的数据必须是有确定范围的整数。
桶排序是计数排序的升级版。它利用了函数的映射关系,高效与否的关键就在于这个映射函数的确定。桶排序 (Bucket sort)的工作的原理:假设输入数据服从均匀分布,将数据分到有限数量的桶里,每个桶再分别排序(有可能再使用别的排序算法或是以递归方式继续使用桶排序进行排)。
计数排序算法描述:
1.找出待排序的数组中最大和最小的元素;
2.统计数组中每个值为i的元素出现的次数,存入数组C的第i项;
3.对所有的计数累加(从C中的第一个元素开始,每一项和前一项相加);
4.反向填充目标数组:将每个元素i放在新数组的第C(i)项,每放一个元素就将C(i)减去1。
桶排算法描述:
设置一个定量的数组当作空桶;
遍历输入数据,并且把数据一个一个放到对应的桶里去;
对每个不是空的桶进行排序;
从不是空的桶里把排好序的数据拼接起来。
举个栗子:(计数/桶升序):2 3 8 7 1 2 2 2 7 3 9 8 2 1 4 2 4 6 9 2
基数排序是按照低位先排序,然后收集;再按照高位排序,然后再收集;依次类推,直到最高位。有时候有些属性是有优先级顺序的,先按低优先级排序,再按高优先级排序。最后的次序就是高优先级高的在前,高优先级相同的低优先级高的在前。
这个很简单,举个栗子就明白了。 (ง •_•)ง
之前的栗子:3 44 38 5 47 15 35 26 27 2 46 4 19 50 48
ㄟ(≧◇≦)ㄏ
比较类排序:通过比较来决定元素间的相对次序,由于其时间复杂度不能突破O(nlogn),因此也称为非线性时间比较类排序。
非比较类排序:不通过比较来决定元素间的相对次序,它可以突破基于比较排序的时间下界,以线性时间运行,因此也称为线性时间非比较类排序。
稳定:如果a原本在b前面,而a=b,排序之后a仍然在b的前面。
不稳定:如果a原本在b的前面,而a=b,排序之后 a 可能会出现在 b 的后面。
时间复杂度:对排序数据的总的操作次数。反映当n变化时,操作次数呈现什么规律。
空间复杂度:是指算法在计算机内执行时所需存储空间的度量,它也是数据规模n的函数。
[]( ̄▽ ̄)*
写在后面:
之前一直想写篇总结排序的算法的。。。但是拖延症晚期。。。这篇博客在草稿箱躺了大半年。。。╥﹏╥…
总之其实有很多排序时间长了忘得差不多了,经过这次总结收获还是很大滴
<(^-^)>。
感谢博客:
https://www.cnblogs.com/onepixel/articles/7674659.html
https://www.cnblogs.com/l199616j/p/10741093.html