目录
从玩牌到编程:揭开插入排序的神秘面纱
大家平时玩扑克牌的时候,有没有注意过自己是怎么整理手中的牌的呢?假设你正在玩斗地主,刚拿到手的牌是杂乱无章的,比如 5、2、4、6、1、3 。通常,我们会从第二张牌开始,将它与前面已经整理好的牌进行比较,然后找到合适的位置插入,让手中的牌始终保持有序。这个看似简单的整理扑克牌的操作,其实蕴含着一种经典的数据结构排序算法 —— 插入排序。
插入排序(Insertion Sort)作为一种基础的排序算法,在计算机科学领域有着广泛的应用。它的核心思想和我们整理扑克牌的过程如出一辙,简单直观,却又充满智慧 。接下来,就让我们深入探索插入排序的世界,看看它是如何在代码的世界里实现高效排序的。
一、插入排序的基本原理
(一)逐步解析排序过程
为了更清晰地理解插入排序,我们通过一个具体的数组 [5, 2, 4, 6, 1, 3] 来详细演示其排序过程。
初始状态:
-
我们将数组分为已排序和未排序两部分。初始时,已排序部分只有第一个元素 5,未排序部分是 [2, 4, 6, 1, 3]。可以想象成手中已经有一张牌 5,桌子上还有 2, 4, 6, 1, 3 这些牌等待整理。
第一轮排序:
-
从未排序部分取出第一个元素 2。现在要把 2 插入到已排序部分 [5] 中合适的位置。
-
将 2 与已排序部分的元素从后往前比较,发现 2 小于 5,于是将 5 向后移动一位,把位置腾出来给 2。
-
此时数组变为 [2, 5, 4, 6, 1, 3],已排序部分变为 [2, 5],未排序部分为 [4, 6, 1, 3]。这就好比把桌子上的一张小牌 2 插到了手中牌 5 的前面,让手中的牌依然保持有序。
第二轮排序:
- 从未排序部分取出元素 4,将其插入已排序部分 [2, 5]。
- 从后往前比较,4 小于 5,将 5 后移一位;再比较,4 大于 2,所以 4 插入到 2 和 5 之间。
- 数组变为 [2, 4, 5, 6, 1, 3],已排序部分更新为 [2, 4, 5],未排序部分是 [6, 1, 3]。就像是又从桌子上拿了一张牌 4,插到了手中合适的位置,使得手中的牌还是有序的。
第三轮排序:
- 取出未排序部分的 6,插入已排序部分 [2, 4, 5]。
- 从后往前比较,6 大于 5,大于 4,也大于 2,所以 6 直接放在已排序部分的末尾。
- 数组变为 [2, 4, 5, 6, 1, 3],已排序部分为 [2, 4, 5, 6],未排序部分是 [1, 3]。相当于拿了一张大牌 6,直接放到了手中已有的有序牌的最后面。
第四轮排序:
- 取出 1 插入已排序部分 [2, 4, 5, 6]。
- 从后往前依次比较,1 小于 6,6 后移;1 小于 5,5 后移;1 小于 4,4 后移;1 小于 2,2 后移,最后把 1 插入到最前面。
- 数组变为 [1, 2, 4, 5, 6, 3],已排序部分是 [1, 2, 4, 5, 6],未排序部分只剩 [3]。就像是拿到一张最小的牌 1,把手中比它大的牌都往后移,然后把它插到最前面。
第五轮排序:
- 取出最后一个未排序元素 3 插入已排序部分 [1, 2, 4, 5, 6]。
- 从后往前比较,3 小于 6,6 后移;3 小于 5,5 后移;3 大于 2,所以 3 插入到 2 和 4 之间。
- 最终数组变为 [1, 2, 3, 4, 5, 6],整个数组都已排序完成。这一步就像是把最后一张牌 3 也找到了它在手中有序牌中的正确位置。
(二)直观理解核心思想
插入排序的核心思想可以简单概括为:构建有序序列。在排序过程中,始终保持已排序部分是有序的,然后不断地从未排序部分取出元素,通过比较和移动已排序部分的元素,将其插入到合适的位置,从而使有序部分逐渐扩大,直到整个数组都有序。就像我们整理扑克牌一样,每次从无序的牌堆中拿一张牌,插入到手中已整理好的牌的合适位置,让手中的牌一直保持有序状态 ,直到所有牌都整理完毕。 这种思想使得插入排序在实现上非常直观,易于理解和编程实现 。 它就像是一个有条不紊的整理过程,每一步都在为最终的有序结果做贡献。
二、代码实战:插入排序的具体实现
(一)以 Python 代码为例
def insertion_sort(arr):
for i in range(1, len(arr)):
key = arr[i]
j = i - 1
while j >= 0 and key < arr[j]:
arr[j + 1] = arr[j]
j -= 1
arr[j + 1] = key
return arr
# 示例数组
arr = [5, 2, 4, 6, 1, 3]
sorted_arr = insertion_sort(arr)
print("排序后的数组:", sorted_arr)
下面逐行解释这段代码的含义:
定义函数:def insertion_sort(arr):,定义了一个名为insertion_sort的函数,它接受一个列表arr作为参数,这个列表就是我们要进行排序的数组。
外层循环:for i in range(1, len(arr)):,这里的range(1, len(arr))表示从索引 1 开始,到数组的最后一个元素结束。这意味着我们从数组的第二个元素开始,将其作为当前要插入到已排序部分的元素,因为第一个元素默认已经在已排序部分。
保存当前元素:key = arr[i],将当前要插入的元素保存到key变量中,方便后续比较和插入操作。
初始化前一个元素的索引