排序算法之python直接插入排序

直接插入排序

介绍:

    直接插入排序是一种最简单的插入排序。有降序和升序两种。

思想:

序列分为两个部分,前半部分是有序序列,后半部分是无序序列,每次从无序序列里取一个放在有序序列的合适位置。直到无序序列为空。
 

代码:

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]
  • 0
    点赞
  • 5
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值