插入排序
输入:n个数的一个序列
输出:输出序列的升序排列
思想:开始时序列视为乱序,然后将第n个数与下标在它之前的数从后往前一次比较并按升序选择合适位置插入,直到整个序列为升序为止。
伪代码如下
INSERTION-SORT(A)
for j = 2 to A.length
key = A[j]
i = j - 1
while i > 0 and A[i] < key
A[i+1] = A[i]
i = i - 1
A[i+1] = key
使用python实现如下
def insertion_sort_esc(arr):
for j in range(1, len(arr)):
key = arr[j]
i = j - 1
# 为key找到合适的位置
while i >= 0 and arr[i] > key:
arr[i + 1] = arr[i]
i = i - 1
arr[i + 1] = key
使用循环不等式证明算法的正确性
- 初始化:循环的第一次迭代前,它为真
- 保持:如果循环的某次迭代之前它为真,那么下次迭代之前它仍然为真
- 终止:再循环终止时,不变式为我们提供一个有用的性质,该性质有助于证明算法是正确的
练习
2.1-1 说明INSERTION-SORT在数组A=<31,41,59,26,41,58>上的执行过程
2.1-2 重写INSERTION-SORT,使之按非升序(而不是非降序)排列。
对于改变顺序,只需要改变第n个数与之之前的比较结果即可
def insertion_sort_desc(arr):
for j in range(1, len(arr)):
key = arr[j]
i = j - 1
while i >= 0 and arr[i] < key:
arr[i+1] = arr[i]
i = i - 1
arr[i+1] = key
2.1-3 考虑一下查找问题:
输入:n个数的一个序列A =
输出:下标i使得v = A[i]或者当v不在A中出现时,v为特殊值为NIL
写出线性查找的伪代码,它扫描整个序列来查找v,使用一个循环不变式来证明你的算法是正确的。确保你的不变时满足三条必要的性质。
写一个简单的顺序查找
SEQUENTIAL-SORT(A, v)
for i = 1 to A.length
if A[i] = v
v = A[i]
v = NIL
循环不变式证明如下:
- 初始化:首先证明在第一次循环迭代之前(当i = 1时, 要么返回A[i], 要么返回NIL),循环不变式成立。
- 保持:for循环体将A从第一位开始到第i位,若A[1...i]中没有找到与v相等的A[i], 只需要再迭代一次进行比较,直到出现A[i]=v为止。那么对下一次迭代也将保持循环不等式。
- 终止:for循环的终止条件是i > A.length = n,即v不在A中。那么当退出for循环时,v为特殊值NIL。因此算法正确。
2.1-4 考虑把两个n位二进制数加起来的问题,这两个整数分别存储在两个n元数组A和B中,这两个整数的和应按二进制形式存储在一个(n + 1)元数组C中。请给出该问题的形式化描述,并给出伪代码。
形式化描述:
输入:n个数的一个序列A =
输出:(n + 1)个数的一个序列C =
伪代码:
BINARY-ADDITIOIN(A, B, C)
n = C.length
for i = A.length downto 1
C[n] = C[n] + A[i] + B[i]
if C[n] >= 2
C[n-1] = C[n-1] + 1
C[n] = C[n] % 2
n = n - 1