排序算法之插入排序(全解+代码)

文章目录

  • 介绍
  • 与其他算法相比
  • 时间复杂度
    • 最好情况时间复杂度
    • 最坏情况时间复杂度
    • 平均情况时间复杂度
  • 改进
  • 代码

介绍

直接插入排序(Insertion Sort)是一种简单的排序算法,其基本思想是将一个待排序的元素插入到已排好序的有序数列中的适当位置,直到全部元素排序完成为止。

具体实现过程如下:

将待排序的数组分成两部分,已排序区间和未排序区间。
初始时,已排序区间只有一个元素,就是数组的第一个元素。
将未排序区间的元素依次插入到已排序区间的适当位置,直到未排序区间为空。
实现过程中,对于每一个待插入的元素,从已排序区间的末尾开始比较,找到插入位置,然后将插入位置之后的元素都向右移动一个位置,最后将该元素插入到插入位置。

插入排序的时间复杂度为O(n^2),空间复杂度为O(1)。它在处理小规模数据时比较高效,但是对于大规模数据排序效率较低。

与其他算法相比

与选择排序、冒泡排序等其他基础排序算法相比,直接插入排序的优点在于:

算法简单易懂,实现容易;
稳定性好,相同元素的顺序不会发生变化;
对于部分有序的序列,排序效率较高。

而直接插入排序的缺点在于,对于规模较大的序列排序效率较低,
时间复杂度为O(n^2),相对于其他高级排序算法来说,排序速度较慢。

综上所述,直接插入排序适合用于对规模较小、部分有序的序列进行排序,但对于规模较大的序列,更适合使用其他高级排序算法,如快速排序、归并排序等。

时间复杂度

直接插入排序的时间复杂度分析如下:

最好情况时间复杂度

在最好情况下,即待排序序列已经是有序的情况下,每次插入一个元素只需要比较一次就可以确定其位置,时间复杂度为 O ( n ) O(n) O(n)

最坏情况时间复杂度

在最坏情况下,即待排序序列是逆序的情况下,每次插入一个元素需要比较 1 , 2 , ⋯   , n − 1 1, 2, \cdots, n-1 1,2,,n1次才能找到其位置,总共需要比较 n ( n − 1 ) 2 \dfrac{n(n-1)}{2} 2n(n1)次,时间复杂度为 O ( n 2 ) O(n^2) O(n2)

平均情况时间复杂度

假设待排序序列中每个元素出现的概率相等,则平均比较次数为 n ( n − 1 ) 4 \dfrac{n(n-1)}{4} 4n(n1),平均时间复杂度为 O ( n 2 ) O(n^2) O(n2)

因此,直接插入排序的最好时间复杂度为 O ( n ) O(n) O(n),最坏和平均时间复杂度均为 O ( n 2 ) O(n^2) O(n2),其时间复杂度与冒泡排序和选择排序相同,但在一些特殊情况下(如待排序序列近乎有序),直接插入排序的性能可能会更好。

改进

直接插入排序的时间复杂度取决于数据的初始状态,如果数据已经近乎有序,则排序的时间复杂度会比较低,但如果数据比较随机,则时间复杂度就会很高。为了优化直接插入排序的性能,可以考虑以下方法:

二分查找法定位插入位置:在查找插入位置时,可以使用二分查找法来代替顺序查找,从而提高查找的效率。具体来说,可以用二分查找法找到第一个大于等于待插入元素的位置,然后将其插入该位置之前。

希尔排序:希尔排序是对直接插入排序的改进,它通过将待排序列分成若干个子序列,对子序列进行插入排序,再逐步缩小子序列的规模,最终完成排序。由于希尔排序在排序前先将数据分组,因此可以让数据进行“大步跳跃”,从而提高排序的效率。

归并排序:归并排序是一种基于分治思想的排序算法,它可以将待排序序列分成若干个子序列,对子序列进行排序,然后再将已排序的子序列合并成一个大序列。与直接插入排序相比,归并排序在处理大规模数据时更加高效。

总之,针对不同的数据特点,我们可以使用不同的排序算法来优化直接插入排序,从而提高排序的效率。

代码

def insertion_sort(arr):
    for i in range(1, len(arr)):
        key = arr[i]
        j = i - 1
        while j >= 0 and arr[j] > key:
            arr[j + 1] = arr[j]
            j -= 1
        arr[j + 1] = key
    return arr

你可能感兴趣的:(数据结构与算法,排序算法,算法,数据结构)