算法复习——6种排序方法的简单回顾
常见排序方法:冒泡排序、选择排序、插入排序、堆排序、归并排序、快速排序的简单回顾
冒泡排序
重复“从序列右边开始比较相邻两个数字的大小,再根据结果交换两个数字的位置”
在冒泡排序中,第 1 轮需要比较 n - 1 次,第 2 轮需要比较 n - 2 次…第 n - 1 轮需要比较 1 次。因此,总的比较次数为 (n - 1) + (n - 2) + … + 1≈n2/2。
时间复杂度:O(n²)
选择排序
重复“从待排序的数据中寻找最小值,将其与序列最左边的数字进行交换”
使用线性查找在数据中寻找最小值,找到最小值1。(详见下一篇文章:数组的查找:线性查找,二分查找)
与最左端数字6交换,即可完成此次操作。
在余下的数字中寻找最小值,重复以上操作:
比较次数:(n - 1) + (n - 2) + … + 1≈n2/2 次
时间复杂度:O(n²)
插入排序
从序列左端开始依次对数据进行排序。插入排序的思路就是从右侧的未排序区域内取出一个数据,然后将它插入到已排序区域内合适的位置上。
首先先排好5在第一个位置。从待排数字(未排序区域)中取出最左边的数字 3,将它与左边已归位的数字进行比较。若左边的数字更大,就交换这两个数字。重复该操作,直到左边已归位的数字比取出的数字更小,或者取出的数字已经被移到整个序列的最左边为止。
时间复杂度:O(n²)
堆排序
利用了数据结构中的堆。关于堆的介绍可以见上一章:数据结构复习-CSDN博客
首先,在堆中存储所有的数据,并按降序来构建堆。
取出第一个数字后,重新构造堆。
重复上述操作直到堆变空为止。
时间复杂度:O(nlogn)
虽然运行时间短,但数据结构相对复杂,实现起来相对困难。
归并排序
把序列分成长度相同的两个子序列,当无法继续往下分时(也就是每个子 序列中只有一个数据时),就对子序列进行归并。
归并:把两个排好序的子序列合并成一个有序序列。
将序列逐次分割。分割完毕后,按从小到大顺序合并。
合并这种含有多个数字的子序列时,要先比较首位数字,再移动较小的数字。
归并排序中,分割序列所花费的时间不算在运行时间内(可以当作序列本来就是分割好的)
无论哪一行都是n个数据,所以每行的运行时间都为 O(n)。而将长度为 n 的序列对半分割直到只有一个数据为止时,可以分成 log2n 行。
时间复杂度:O(nlogn)
快速排序
首先会在序列中随机选择一个基准值(pivot),然后将除了基准值以外的数分为“比基准值小的数”和“比基准值大的数”这两个类别,再将其排列成以下形式。
[ 比基准值小的数 ] 基准值 [ 比基准值大的数 ]
接着,对两个“[ ]”中的数据进行排序之后,整体的排序便完成了。对“[ ]”里面的数据进行排序时同样也会使用快速排序。
举例:随机取4为基准值。将其他数字和基准值进行比较。小于基准值的往左移,大于基准值的往右移。
完成后,再分别对左边和右边的数据进行快速排序,就能完成整体的排序。
快速排序是一种**“分治法”**。它将原本的问题分成两个子问题(比基准值小的数和比基准值大的数),然后再分别解决这两个问题。
像这样,在算法内部继续使用该算法的现象被称为**“递归”**。
时间复杂度:O(nlogn)(如果数据中的每个数字被选为基准值的概率都相等,平均运行时间)
参考资料:我的第一本算法书 (石田保辉 宮崎修一)