一.计数排序
1.概念
计数排序(Counting sort)是一种非基于比较的排序算法,其核心在于将输入的数据值转化为键存储在额外开辟的数组空间中以达到排序的效果。
2.算法原理
2.1建立一个任意长度的计数数组,值初始化为0。遍历无序序列,将每个序列元素值对应的计数数组下标的元素加1。
2.2遍历无序序列,将每个序列元素值对应的计数数组下标的元素加1。
2.3继续遍历序列,序列遍历完毕。
2.4遍历计数数组,输出计数数组下标值,元素的值是多少,就输出几次。
3.时间复杂度
计数排序算法遍历了3次原始数组,一次计数数组,所以算法的时间复杂度是O(N+M)。
4.空间复杂度
计数排序算法排序过程中新建了一个计数数组和一个输出数组,所以算法的空间复杂度是O(N+M)。
5.稳定性
优化后的计数排序算法在排序过程中,相同元素的前后顺序不会发生改变,是一种稳定排序算法。
6.局限性
当待排序序列的最大值和最小值差值特别大时,不适合使用计数排序算法。
当待排序序列的值不是整数时,不适合使用计数排序算法。
二.冒泡排序
1.概念
冒泡排序(Bubble Sort)是排序算法里面比较简单的一个排序。它重复地走访要排序的数列,一次比较两个数据元素,如果顺序不对则进行交换,并一直重复这样的走访操作,直到没有要交换的数据元素为止。
2.算法原理
2.1我们要将某无序数列按从小到大排序。按照冒泡排序的思想,我们要把相邻的元素两两比较,根据大小来交换元素的位置。
2.2经过一轮比较后,某数作为最大的元素到了序列的最右侧。
2.3接下来进行第二轮比较,从最前面两个数开始比较,到最右边的数结束,最大的那个数已经是有序的,不需要再参与比较。
2.4直到所有的元素都是有序的为止。
3.时间复杂度
冒泡排序算法的每一轮要遍历所有元素,轮转的次数和元素数量相当,所以时间复杂度是O(N^2)
经过优化后,最优的情况,序列已经是顺序的,那么只要进行一次循环,所以最优时间复杂度是O(N)
4.空间复杂度
冒泡排序算法排序过程中需要一个临时变量进行两两交换,所需要的额外空间为1,因此空间复杂度为O(1)
5.稳定性
冒泡排序算法在排序过程中,元素两两交换时,相同元素的前后顺序并没有改变,所以冒泡排序是一种稳定排序算法。
三.插入排序
1.概念
插入排序(Insertion Sort)是一种简单直观的排序算法,它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。
2.算法原理
1.1这是一个无序数列:1、5、4、2、6、3,我们要将它按从小到大排序。按照插入排序的思想,我们先指定有序序列,再将无序序列插入有序序列的相应位置。
1.2将第一个元素1作为有序数据,此时有序区只有一个元素。
1.3第一轮,让元素5和有序区依次比较,1<5,无需交换此时有序区有1、5两个元素。
1.4第二轮,让元素4和有序区依次比较,5>4,需要交换。1<4,1与4不需要交换,此时有序区有1、4、5三个元素。
1.5直到所有的元素都是有序的为止。
3.时间复杂度
插入排序算法要进行n-1轮,每一轮对比的元素最坏的情况依次是1, 2, 3 … n-1,所以时间复杂度是O(N^2)
4.空间复杂度
插入排序算法排序过程中需要一个临时变量存储插入元素,所需要的额外空间为1,因此空间复杂度为O(1)
3.稳定性
插入排序算法在排序过程中,无序数列插入到有序区的过程中,不会改变相同元素的前后顺序,是一种稳定排序算法
四.快速排序
1.概念
快速排序(Quick Sort)是从冒泡排序算法演变而来的,实际上是在冒泡排序基础上的递归分治法。快速排序在每一轮挑选一个基准元素,并让其他比它大的元素移动到数列一边,比它小的元素移动到数列的另一边,从而把数列拆解成了两个部分。
2.算法原理
2.1这是一个无序数列:4、5、8、1、7、2、6、3,我们要将它按从小到大排序。按照快速排序的思想,我们先选择一个基准元素,进行排序。
2.2我们选取4为我们的基准元素,并设置基准元素的位置为index,设置两个指针left和right,分别指向最左和最右两个元素。
2.3接着,从right指针开始,把指针所指向的元素和基准元素做比较,如果比基准元素大,则right指针向左移动,如果比基准元素小,则把right所指向的元素填入index中3和4比较,3比4小,将3填入index中,原来3的位置成为了新的index,同时left右移一位
2.4我们切换left指针进行比较,如果left指向的元素小于基准元素,则left指针向右移动,如果元素大于基准元素,则把left指向的元素填入index中5和4比较,5比4大,将5填入index中,原来5的位置成为了新的index,同时right左移一位。
2.5我们再切换到right指针进行比较,6和4比较,6比4大,right指针左移一位。2和4比较,2比4小,将2填入index中,原来2的位置成为新的index,left右移一位。
2.6随着left右移,right左移,最终left和right重合。此时,我们将基准元素填入index中,这时,基准元素左边的都比基准元素小,右边的都比基准元素大,这一轮交换结束。
2.7第一轮,基准元素4将序列分成了两部分,左边小于4,右边大于4,第二轮则是对拆分后的两部分进行比较,此时,我们有两个序列需要比较,分别是3、2、1和7、8、6、5,重新选择左边序列的基准元素为3,右边序列的基准元素为7。
2.8此时,3、4、7为前两轮的基准元素,是有序的,7的右边只有8一个元素也是有序的,因此,第三轮,我们只需要对1、2和5、6这两个序列进行排序。
2.9直到所有的元素都是有序的为止。
3.时间复杂度
快速排序算法在分治法的思想下,原数列在每一轮被拆分成两部分,每一部分在下一轮又分别被拆分成两部分,直到不可再分为止,平均情况下需要logn轮,因此快速排序算法的平均时间复杂度是O(nlogn)
在极端情况下,快速排序算法每一轮只确定基准元素的位置,时间复杂度为O(N^2)
4.空间复杂度
快速排序算法排序过程中只是使用数组原本的空间进行排序,因此空间复杂度为O(1)
5.稳定性
快速排序算法在排序过程中,可能使相同元素的前后顺序发生改变,所以快速排序是一种不稳定排序算法