常用排序算法–冒泡排序及改进和插入排序时间复杂度分析
排序及常见排序算法
排序是计算机内经常进行的一种操作,其目的是将一组“无序”的记录序列调整为“有序”的记录序列。分内部排序和外部排序。若整个排序过程不需要访问外存便能完成,则称此类排序问题为内部排序。反之,若参加排序的记录数量很大,整个序列的排序过程不可能在内存中完成,则称此类排序问题为外部排序。内部排序的过程是一个逐步扩大记录的有序序列长度的过程。
上面是关于排序的一些介绍,排序按是否使用外在存储来分分为内部排序(locally sort)和外部排序(external sort)。下文分析的是内部排序的两种常见的、简单易实现的排序算法,虽然两者的排序算法的时间复杂度在众多内部排序算法中属于下等,但是对于理解内部排序(特别是采用比较排序)的一些机制是十分有用的。
常见的内部排序算法及其时间复杂度主要如下:
- 冒泡排序 冒泡排序通过两两相邻元素比较,每一趟将本趟中最大的元素放在数组尾部合适的位置。由于每一趟只正确放置一个元素,因此时间复杂度为
O(n*n)
- 插入排序 插入排序是通过将当前第
i
个待排元素i
与数组中前i-1
个已经有序的元素j
进行两两比较,如果元素i
小于j
,便交换。直到遇到比i
小的元素或者到达数组头。由于每一个元素的插入都会最多比较i - 1
次,因此最坏的时间复杂度为1 + 2 + 3 + ... + n - 1 = n * (n - 1) / 2
, 因此时间复杂度也为O(n*n)
。 - 希尔排序 插入排序的一种改进,具有优良的时间复杂度,时间复杂度为
O(n*n)
- 快速排序 基于分治的策略排序,时间复杂度为
O(nlgn)
,由于待排数据如果是逆序,其时间复杂度会变为O(n*n)
,因此常用的方法是在排序前先随机化待排数据。 - 归并排序 基于分治的策略排序,时间复杂度为
O(nlgn)
,需要额外的存储空间 - 堆排序 采用二叉树的性质进行排序,不需要额外的内存空间,时间复杂度为
O(nlgn)
- 计数排序 非比较排序,要求输入的数据的范围为
0 ~ K
,时间复杂度为O(n)
- 基数排序 非比较排序,是计算排序的一种变种,对输入数据的要求降低到了数据的的位数为
d
,每一位的范围为0~k
。
插入排序时间复杂度分析
上文中介绍的除了计数排序和基数排序外,其余均为内排序中的比较排序,即通过两元素的比较,来确定元素正确放置的位置。
插入排序算是一种比较经典的比较类排序算法,可以分析其时间复杂度,然后确定其最坏和平均时间复杂度,从而来确定时间复杂度的最低边界。
由于没有比较,就不会有元素的交换,因此元素的交换次数是小于等于
最坏时间复杂度分析:若输入的n
个数据是逆序的,那么对第i
个元素的插入,需要比较i-1
次,因此总的时间复杂度为为n*(n - 1) / 2
平均时间复杂度分析:对于第i
个元素的插入,该元素有i + 1
个位置可以插入,平均来看,插入每一个位置的概率都相同为1 / (i + 1)
;对于每一个位置比较的次数分别为1, 2, 3, 4, 5 ... i, i
,因为当i
元素为最小和次小的时候,比