为何插入排序比冒泡排序更受欢迎

对于任何一个程序员来讲,学习的第一个算法,可能就是排序。最经常使用的有:冒泡排序、计数排序、插入排序、快速排序、选择排序等。 其中:冒泡排序、插入排序、选择排序的时间复杂度为O(n^2),且是基于比较的排序算法。程序员

思考:插入排序和冒泡排序的时间复杂度相同,都是O(n2),在实际的软件开发里,为何咱们更倾向于使用插入排序算法而不是冒泡排序算法呢?算法

如何分析一个"排序算法"

学习排序算法,除了学习他的算法原理、代码实现以外,更重要的是要学会如何评价、分析一个排序算法。分析一个排序算法,通常从下面几个方面入手:数组

排序算法的执行效率

  1. 最好状况、最坏状况、平均状况时间复杂度
  2. 时间复杂度的系数、常数、低阶
  3. 比较次数和交换(或移动)次数(排序算法的内存消耗,排序算法的稳定性)

冒泡排序解析

1、冒泡排序是原地排序算法吗?

冒泡的过程只涉及相邻数据的交换操做,只须要常量级的临时空间,因此它的空间复杂度为O(1),是一个原地排序算法。bash

2、冒泡排序是稳定的排序算法吗?

在冒泡排序中,只有交换才能够改变两个元素的先后顺序。为了保证冒泡排序算法的稳定性,当有相邻的两个元素大小相等的时候,咱们不作交换,相同大小的数据在排序先后不会改变顺序,因此冒泡排序是稳定的排序算法。性能

3、冒泡排序的时间复杂度是多少?

最好状况下,要排序的数据已是有序的了,咱们只须要进行一次冒泡操做,就能够结束了,因此最好状况时间复杂度是O(n)。而最坏的状况是,要排序的数据恰好是倒序排列的,咱们须要进行n次冒泡操做,因此最坏状况时间复杂度为O(n^2)学习

插入排序解析

1、插入排序是原地排序算法吗?

从实现过程能够明显看出,插入排序算法的运行并不须要额外的存储空间,因此它的空间复杂度为O(1),是一个原地排序算法。优化

2、插入排序是稳定的排序算法吗?

在插入排序中,对于值相同的元素,咱们能够选择将后面出现的元素,插入到前面出现元素的后面,这样就能够保持原有的先后顺序不变,因此插入排序的稳定的排序算法。spa

3、插入排序的时间复杂度是多少?

若是要排序的数据已是有序的,咱们并不须要搬移任何数据。若是咱们从尾到头在有序数据组里面查找插入位置,每次只须要比较一个数据就能肯定插入的位置。因此这种状况下,最好的时间复杂度为O(n)。code

若是数组是倒序的,每次插入都至关于在数组的第一个位置插入新的数据,因此须要移动大量的数据,因此最坏的事件复杂度为O(n^2).排序

冒泡排序和插入排序的时间复杂度都是O(n^2),都是原地排序算法,为何插入排序要比冒泡排序更受欢迎呢?

从前面的分析能够得出:冒泡排序无论怎么优化,元素交换的次数是一个固定值,就是原始数据的逆序度。插入排序是一样的,无论怎么优化,元素移动的次数也等于原始数据的逆序度。

可是从代码实现上来看,冒泡排序的数据交换要比插入排序的数据移动要复杂,冒泡排序须要3个赋值操做,而插入排序只须要1个。

冒泡排序中数据的交换操做
if (a[j] > a[j+1]) { // 交换
    int tmp = a[j]
    a[j] = a[j+1]
    a[j+1] = tmp
    flag = true
}

插入排序中数据的移动操做
if (a[j] > value) {
    a[j+1] = a[j] // 数据移动
}
复制代码

咱们把执行一个赋值语句的时间粗略地计为单位时间(unit_time),而后分别用冒泡排序和插入排序对同一个逆序度是K的数组进行排序。用冒泡排序,须要k次交换操做,每次须要3个赋值语句,因此交换操做总耗时就是 3*K 单位时间。而插入排序中数据移动操做只须要K个单位时间。

总结:

因此,虽然冒泡排序和插入排序在时间复杂度上都是同样的,都是O(n^2),但若是咱们但愿把性能作到极致,那确定首选插入排序。固然,插入排序的算法思路也有很大的优化空间,所以又出现了希尔排序

相关文章
相关标签/搜索