直接插入排序
介绍:
直接插入排序是一种最简单的插入排序。有降序和升序两种。
思想:
序列分为两个部分,前半部分是有序序列,后半部分是无序序列,每次从无序序列里取一个放在有序序列的合适位置。直到无序序列为空。
代码:
def InsertSort(input_list):
if len(input_list) == 0:
return []
sorted_list = input_list
for i in range(1,len(input_list)):
#将待排元素赋给临时变量
temp = sorted_list[i]
#从待排元素前一个元素开始寻找temp的合适位置
j = i-1
#没有找到合适位置就让将空出的位置向前移动
while j>= 0 and temp < sorted_list[j]:
sorted_list[j+1] = sorted_list[j]
j -=1
#找到合适位置将temp放在该位置
#因为循环里是先移动再让j减一了,故合适位置应该在j+1的位置
sorted_list[j+1] = temp
print("%dth"%i)
print(sorted_list)
return sorted_list
if __name__ == '__main__':
input_list = [50,123,543,187,49,30,0,2,11,100]
print("input_list:")
print(input_list)
sorted_list = InsertSort(input_list)
print("sorted_list:")
print(sorted_list)
结果:
input_list:
[50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
1th
[50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
2th
[50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
3th
[50, 123, 187, 543, 49, 30, 0, 2, 11, 100]
4th
[49, 50, 123, 187, 543, 30, 0, 2, 11, 100]
5th
[30, 49, 50, 123, 187, 543, 0, 2, 11, 100]
6th
[0, 30, 49, 50, 123, 187, 543, 2, 11, 100]
7th
[0, 2, 30, 49, 50, 123, 187, 543, 11, 100]
8th
[0, 2, 11, 30, 49, 50, 123, 187, 543, 100]
9th
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
sorted_list:
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
分析:
1.算法性能
2.时间复杂度
当数据正序时,执行效率最好,每次插入都不用移动前面的元素,时间复杂度为O(N)。
当数据反序时,执行效率最差,每次插入都要前面的元素后移,时间复杂度为O(N^2)。
所以,数据越接近正序,直接插入排序的算法性能越好。
3.空间复杂度
需要一个临时变量temp,故为1
4.算法稳定性
在sorted_list[j+1]=temp是在不小于的情况下,故相等时是不交换的,所以直接插入排序是一种稳定排序算法
5.优化
因为在寻找temp的合适插入位置时用的是从后往前查找,我们可以用二分查找减少因此产生的元素交换次数
二分查找每次从序列的中间查找该元素是否等于插入元素,若插入元素比中间元素小,则继续在中间元素的左边继续二分查找;
若插入元素比中间元素大,则继续在中间元素的右边继续二分查找。
代码:
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
#将temp放入合适位置
result[j + 1] = temp
print("%dth"%i)
print(result)
return result
#二分查找
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
if __name__ == '__main__':
input_list = [50,123,543,187,49,30,0,2,11,100]
print("input_list:")
print(input_list)
sorted_list = BinaryInsertSort(input_list)
print("sorted_list:")
print(sorted_list)
结果:不变,只是内部查找合适位置的次数减少了,由O(n)变成了O(lgn),提高了效率
input_list:
[50, 123, 543, 187, 49, 30, 0, 2, 11, 100]
1th:
[50, 123, 187, 49, 30, 0, 2, 11, 100, 543]
2th:
[50, 123, 49, 30, 0, 2, 11, 100, 187, 543]
3th:
[50, 49, 30, 0, 2, 11, 100, 123, 187, 543]
4th:
[49, 30, 0, 2, 11, 50, 100, 123, 187, 543]
5th:
[30, 0, 2, 11, 49, 50, 100, 123, 187, 543]
6th:
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
7th:
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]
sorted_list:
[0, 2, 11, 30, 49, 50, 100, 123, 187, 543]