python实现插入排序
preparing for a satisfying offer-------重温算法 day 1
方法1:新开辟一个列表存储
这种方法需要一个新的、同样长度的列表存储空间。
原理
- 给定若干个待排序的数,先把这些数放到列表中;
- 先从这些数中拿出一个记为num1,放在一个新的列表的第一位;
- 再从剩下的数中拿出一个num2和num1比较,比num1大就放到num1后面,小则放在num1前面,此时需要先把num1后移一位,num2才能放到num1前面的空位上。
- 继续从剩下的数中拿出一个num3和num1,num2的有序列比较,并按大小插入,同样插入前需要把后面的数依次后移一位,从而将num3要插入的位置空出来;
- 同样的方法依次插入所有的数;
- 结束条件:原有列表中的所有数都已经插入到新列表中;
代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
lt=[49,38,65,97,76,13,27]
length=len(lt)
newlt=[49] #新开辟的存储位置
for i in lt[1:]:
tag = False
for j in range(0,len(newlt)):
if i<newlt[j]:#比较大小,寻找插入位置,比较j次
tag=True
newlt.append(0)
for k in range(len(newlt)-1,j,-1):#确定插入位置后,开始移动元素,移动length-j次
newlt[k]=newlt[k-1]
newlt[j]=i
print(newlt)
break#结束此次插入
if not tag:
newlt.append(i)
评价
插入排序本身的时间复杂度为O(n2),但这种方法还需要对原列表进行遍历。
另外这种方法所需的额外存储空间较大。但优点是比较容易理解。
方法2:在原列表的基础上进行排序
这种方法只可能需要一个较短长度的新列表存储空间。
原理
- 给定若干个待排序的数,先把这些数放到列表中;
- 每次取出这个列表的最后一位num;
- 从该列表的第一位开始和num进行比较,直到碰到比num大的第j位,则先把从第j位开始后面的都依次向后移一位,然后把num放在该列表的第j位。
- 若num值比前面其他的数都大,则不会产生移位,num依然在最后一位,因为每次取出这个列表的最后一位,所以这样以后都会循环取出num,为了避免这种情况,先把num拿出来存到一个新的列表中;
- 循环2,3或2,4步骤;
- 结束条件:循环次数达到原数组的长度数值;
- 将循环最后的结果——部分有序列表和暂存在新列表中的数拼接起来。
代码
#!/usr/bin/env python
# -*- coding:utf-8 -*-
lt=[49,38,65,97,76,13,27]
count=len(lt)#将数组长度存下来,作为迭代总次数
temp=[]#用来存储下面不会导致移位的‘大’数
while count:
count-=1#每迭代一次,总次数减一,以此作为退出while循环的判断条件
point = lt[-1]
#每次拿出列表的最后一位作为接下来要插入的数,从而相比第一种方法,省去对原列表的循环
tag = True
#如果要插入的数是最大的,则其经过一轮比较后仍然会留在数组最后,
# 此后就如此循环,所以要暂时把这个最大的数存到一个新的列表中。
for i in range(0,len(lt)):
if point<lt[i]:
tag=False#证明正在比较的这个数不是最大的
for j in range(len(lt)-1,i,-1):
lt[j]=lt[j-1]
lt[i]=point
print(1,lt)
break
if tag:#证明正在比较的这个数是最大的
temp.append(lt[-1])
lt=lt[:-1]
print(2,lt)
for k in range(len(temp)-1,-1,-1):#将存储在temp中的‘大’数倒序取出连接到已经排好序的数组后面
lt.append(temp[k])
print(lt)
评价
这种方法有点儿绕,但是不需要对原有列表进行遍历,也只可能需要较短的新列表存储空间。