第二章-算法入门
总结:这一章讲了插入排序及其算法分析,循环不变式的证明,合并排序(分治法)及其算法分析。
1. 插入排序
类似于扑克牌的插入过程,设A[1...j-1]是排好序的一个数组,将A[j]插入A[1...j-1]中使A[j]称为排好序的一个数组,j <- 2 to length[A]
算法分析:最好情况,整个数组已经是顺序的了,O(n)
最坏情况,整个数组是逆序的,O(n^2)
平均情况,O(n^2)
是一种稳定排序
算法优化:将A[j]插入已经排好序的A[1...j-1]时,可以用二分查找法,这可以改变查找合适位置的效率,但是仍需要将数组的元素一个一个移动。
伪代码
C++代码
2. 循环不变式
证明三个性质:初始化、保持、终止
3. 合并排序
分治法:将原问题分成n个规模较小而结构与原问题相似的子问题;递归地解决这些子问题,然后再合并其结果,就得到原问题的解。
算法分析:时间复杂度O(nlgn)
空间复杂度O(n)
稳定排序
C++代码
【练习题】
1. 选择排序
从A中找到最小的元素,与A[0]互换,再从A中找出次最小元素,与A[1]互换,以此类推..
算法分析:时间复杂度 O(n^2)
稳定排序
伪代码:
问题:为什么i的循环只要到length[A]-1,因为到时前n-1个一定是最小的n-1个,那么第n个必定是最大的那个元素,所以最后一次循环可以省去了。
C++代码:
2. 二分查找(时间复杂度O(lgn))
1) 非递归(迭代)
2) 递归
3. 请给出一个运行时间为O(nlgn)的算法,使之能在给定一个由n个整数构成的集合S和另一个整数x时,判断出S中是否存在两个其和等于x的元素。
算法思路:
思路一:对S排序(O(nlgn)),去掉S中重复的元素(O(n)),对S中的每个元素y,计算z=x-y,将所有的z汇集成S’(O(n)),对S’排序(O(nlgn)),合并S,S’。若合并的集合中存在两个连续相等的元素,则说明S中存在两个其和等于x的元素。
思路二:对S排序(O(nlgn)),对S中的元素y,计算z=x-y,从S中二分查找z(O(lgn)),找到则说明存在。最多循环n次,复杂度O(nlgn)
【思考题】
1. 用O(nlgn)的复杂度求给定n个元素的任何排列中逆序对的数目(提示:修改合并排序)