直接插入排序是一种最简单的插入排序。
这里我们主要学习直接插入升序排序。
1.什么是插入排序:
每一趟将一个待排序的记录,按照其关键字的大小插入到有序队列的合适位置里,直到全部插入完成。
例子:
在打扑克牌的时候:
你手里有一张5,
再摸到一张4,比5小,插到5前面,
又摸到一张6,比5大,插到5后面,
再摸到一张7,比6大,插到6后面
…
这就是典型的直接插入排序,每次将一个新数据插入到有序队列中的合适位置里。
2.算法思想:
假设我们现在有一组待排序的序列 D0,D1,D2,…,Nn-1
(1)我们先将这个序列下标为0的元素D0视为个数为1的有序序列
(2)然后,我们将D1,D2,…,Nn-1插入到这个有序序列中。所以,我们需要一个外部循环,从下标 1 扫描到 n-1 。
(3)假设这是要将 Di 插入到前面有序的序列中,由前面所述,我们可知,插入Di时,前 i-1 个数肯定已经是有序了。
所以我们需要将Di 和D0 ~ Di-1 进行比较,确定要插入的合适位置。这就需要一个内部循环,我们一般是从后往前比较,即从下标 i-1 开始向 0 进行扫描。
3.python3代码实现:
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 10 11:44:36 2019
@author: ZQQ
"""
def insertSort(input_list):
n = len(input_list) # 计算待排序序列长度
if n <= 1: # 已有序,或为空,直接返回
return input_list
else:
# 第一层循环表示插入的遍数
for i in range(1,n): # i取 1,2,3,..., n-1
# 当前待插入的元素
current = input_list[i]
# 已经有序元素的索引
pre_index = i - 1
while pre_index >= 0 and input_list[pre_index] > current:
# 当 比较元素 > 当前元素, 则把比较元素后移
input_list[pre_index + 1] = input_list[pre_index]
# 往前选择下一个比较元素
pre_index -= 1
# 当 比较元素 < 当前元素,或不满足pre_index>=0,则将 当前元素 插入其后面
input_list[pre_index + 1] = current
print(input_list)
return input_list
input_list = [6, 4, 8, 9, 2, 3, 1]
print('排序前:', input_list)
sorted_list = insertSort(input_list)
print('排序后:', sorted_list)
实验结果:
4.算法分析:
插入排序的适用场景:一个新元素需要插入到一组已经是有序的数组中,或者是一组基本有序的数组排序。
(1)比较性:排序时元素之间需要比较,所以为比较排序
(2)稳定性:从代码我们可以看出只有比较元素大于当前元素,比较元素才会往后移动,所以相同元素是不会改变相对顺序,稳定排序。
(3)时间复杂度:插入排序同样需要两次循坏一个一个比较,故时间复杂度为O(n^2)
(4)空间复杂度:只需要常数个辅助单元,所以空间复杂度为O(1)
(5)复杂性:简单
注:当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N^2)。
所以,数据越接近正序,直接插入排序的算法性能越好。
平均情况:O(N^2)
5.算法优化:
因为在一个有序序列中查找一个插入位置,以保证有序序列的序列不变,所以可以使用二分查找,减少元素比较次数提高效率。
二分查找是对于有序数组而言的,假设如果数组是升序排序的,那么,二分查找算法就是不断对数组进行对半分割,每次拿中间元素和目标数字进行比较,如果中间元素小于目标数字,则说明目标数字应该在右侧被分割的数组中,如果中间元素大于目标数字,则说明目标数字应该在左侧被分割的数组中。
# -*- coding: utf-8 -*-
"""
Created on Wed Jul 10 15:46:21 2019
@author: ZQQ
"""
~~~python
# -*- coding:utf-8 -*-
def BinarySearch(input_list, end, value):
left = 0
right = end - 1
while left <= right:
middle = left + (right - left) // 2
if input_list[middle] >= value:
right = middle - 1
else:
left = middle + 1
return left if left < end else -1
def BinaryInsertSort(input_list):
if len(input_list) == 0:
return []
result = input_list
for i in range(1, len(input_list)):
j = i - 1
temp = result[i]
insert_index = BinarySearch(result, i, result[i])
if insert_index != -1:
while j >= insert_index:
result[j + 1] = result[j]
j -= 1
result[j + 1] = temp
return result
input_list = [6, 4, 8, 9, 2, 3, 1]
print('排序前:', input_list)
sorted_list = BinaryInsertSort(input_list)
print('排序后:', sorted_list)