2.1插入排序
1.关键词:希望排序的数。
2.工作方式:(类似排序扑克牌)开始时,我们的左手为空并且桌子上的扑克牌牌面朝下。然后,我们每次从桌子上拿走一张扑克牌并将它插入到左手中的正确位置。为了找到一张牌的正确位置,我么需要从右到左将它与已在手中的每张牌进行比较。拿在手里的牌总是排好序的,原来这些牌是桌子上牌堆顶部的牌。 3.循环不变式:(三条性质)
初始化:循环的第一次迭代之前,它为真;
保持: 如果循环的某次迭代之前它为真,下一次迭代之前它仍为真。
终止:在循环终止时,不变式为我们提供了一个有用的性质,该性质有助于证明算法是正确的:
练习:
2.1-1:以图2-2为模型,说明INSERTION-SORT在数组A = <31,41,59,26,41,58>上的执行过程。
答:(验证一下循环不变式):在循环的第一次迭代之前,A[1] = 31,只有一个元素,是有序的,当然为真;当j = 2时,原有的数组的子集已经有序,为真,经过一次迭代,原有的子集B = <31,41>变成B<31,41>且为有序。满足下一次迭代之前仍为真。
当j = n+1时,子集中的元素都是有序的并且和A相等,故在循环终止的时候,整个数组都变成有序的。
执行过程:j = 1时,B= [31],有序;
j = 2时,B= [31,41],也是有序的;
j = 3时,B = [31,41,59],有序;
i= 4时,B = [31,41,59,26];i = 3,B = [31,41, ,59];i = 2,B = [31, , 41,59];i = 1,B = [ ,31,41,59];最后将26放置在第一个位置,得 到 B= [26,31,41,59]。
j = 4时,B= [26,31,41,59,41]以及j = 5重复上述过程。
2.1-2重写INSERTION-SORT,使之按非升序(而不是非降序)排序。
for(j = 2; j <= n; j++){
key = A[j];
i = j-1;
while(i >0 && A[i] < key){
A[i+1] = A[i]
}
A[i+1] = key;
}
2.1-3考虑一下查找问题:
输入: n个数的一个序列A = <a1,a2,……an>和一个值v。
输出:下标i使得v = A[i] 或者当v不在A中出现时,v为特殊的值NIL。
写出线性查找的伪代码,它扫描整个序列来查找v。使用一个循环不变式来证明你的算法是正确的。确保你的循环不变式满足三条必要的性质。
2.1-4:考虑把两个n位二进制加起来的问题,这两个数分别存储在两个n元数组A和B中。考虑这两个整数的和应该按二进制形式存储在一个(n+1)元数组C中。请给出该问题的形式化描述,并写出伪代码。
形式化描述:将数组A中的每一个元素和数组B中的每一个元素相加,再加上进位,对2
区域后余数保存在C中,进位保存在进位count中。
所有位相加结束后,如果有进位,将进位保存在数组C中
最后逆置数组C。
伪代码:
BINARY_ADD(A,B,C)
count; //表示进位
temp;
i = 0;
for j = n downto 1
temp = A[j] + B[j] + count;
C[i] = temp % 2;
count = temp /2;
if count != 0
C[i] = count;
reverse(C); //翻转数组C