知识总结
插入排序:
对于插入排序法很形象的描述就是,打牌的你手上握着一手无序的牌,现在你需要将它们按顺序排好。
于是,你从第二张牌开始,对比和之前的牌的大小并选择正确的位置插入。
第二张牌插完了,就拿第三张牌和前面两张牌比较,然后插入合适的位置。
如此到最后一张牌结束。
下面用代码简单实现一下(Java)。
private int[] insertion(int[] arr) { for (int i = 1; i < arr.length; i++) { int key = arr[i]; int j = i-1; while (j >= 0 && arr[j] > key) { arr[j + 1] = arr[j]; j--; } arr[j + 1] = key; } return arr; }
循环不变式:
- 初始化: 第一次循环前不变式成立
- 保持:每次迭代保持不变式成立
- 终止;循环结束时验证
习题
2.1-2
重写过程INSERTION-SORT, 使之按非升序(而不是非降序)排序。
答:只要把 arr[j] > key 改成 arr[j] < key 就可以了。
关于非升序和非降序,一开始感到很迷惑,非升序不就是降序吗?后来一想,可能是考虑到相等的情况才有此一说。
2.1-3
输入:n个数的一个序列A和一个值v
输出:存在v = A [ i ]时,输出i,不存在时输出Nil (书上的翻译简直反人类)
答:
初始化:循环开始前,没有符合条件的项,result = Nil成立result = Nil for i = 1 to n if A[ i ] == v do result = i return result
保持:循环中,若没有符合条件的项,则result不改变,符合条件的项出现时,result为i,成立
终止:循环结束后,若没有符合条件的项,result为Nil ,否则为下标 i ,成立。
2.1-4
两个n位二进制整数相加。两个整数分别存在两个n元数组A和B中。两个数字的和按二进制存在一个n+1元数组C中。
答:
从最低位开始做加法,flag表示进位,初始为0。flag = 0 for i = n downto 1 r = A[i] + B[i] + flag if r == 2 flag = 1 r = 0 else flag = 0 C[ i + 1 ] = r C[1] = flag
当某一位上的两个数字加上flag达到了2,则进位为1同时置该位的结果为0。
若没有达到2,则进位为0。
然后把该位的计算结果存入C数组相应的位置也就是i+1处。
循环结束后,进位就是结果的最高位,存入C数组的最高位C[1]。