一.插入排序算法
问题简介
最古老的算法问题
输入<a1,a2, .... ,an>
输出<a1',a2', .... ,an'> 且有(Such that$) a1'≤a2'≤ .... ≤an'
插入排序原理分析
输入规模: 不同问题的定义不同,此处的度量为 项数
运行时间: 执行的基本操作的"步数"
插入排序(Insert Sort)代码
1 Insert_Sort(A)
2 for j=[2 -> A.Length]
3 key = A[j]
4 i = j - 1
5 while i between[1 , j-1] and A[i]>key
6 A[i+1] = A[i]
7 i = i- 1
8 A[i+1] = key
Copy
JavaScript
代码时间分析
其中有x取决于具体的数据输入,x最坏为,构成一个
代码细节解析
保存目前的 将要被排序位 A[Key], 范围为[2,A.length]
A.length == 1的情况?
将 Key位 的前一位作为 比较位A[i]
比较A[i]和A[key]
A[i]>A[key] : 向后搬移一位 i=i-1 再次循环
A[i]<A[key] : 向后搬移一位 A[i]=A[key]
二.循环表达式证明
插入排序
假设我们以A[1:j]是否有序作为循环表达式的判定条件
起始: A[1:1]显然有序
循环: 若A[1:j-1]有序经过循环后可证明A[1:j]也是有序的
结束: 结束时候j=A.length 等价于 A[1:A.length]有序
三.分治法的归并排序
分治法步骤
分解: 分解成若干个子问题
解决: 解决子问题,子问题足够小时候直接求解
合并: 合并子问题
归并排序关键
关键是合并(Merge)两个已排序的子序列
合并的基本思路是通过两个下标,逐项比较.
Merge 的实现
Merge(A , p , q , r)
n1 = q-p+1 (计算子序列n1长度)
n2 = r-(q+1)-1 (计算子序列n2长度)
Let L[1:n1+1] R[1:n2+1] become new arrays
(将两个子序列拷贝到缓冲区L(eft) R(ight)数组中)
copy A[p:q] to L[1:n1]
copy A[q+1:r] to R[1:n2]
(设置哨兵元素,供接下来的比较标识行尾)
L[n1+1] = infinite
R[n2+1] = infinite
init i1 = 1, i2 =1 ;(建立指针index)
for(init k = p; k==r ; k++)
{
if L[i1]<R[i2] then { A[k]=L[i1]; i1++}
else then { A[k]=R[i2]; i2++}
}
Copy
C++
Merge-Sort (A , p , r)
{
if(p == r) then { return } (直接相当于排序好了)
else
{
q = ⌊ p+q/2 ⌋ (向下取整)
Merge-Sort (A , p , q)
Merge-Sort (A , q+1 , r)
Merge(A,p,q,r)
}
}
Copy
C++
Merge 代码分析
计算子序列n1长度 n2长度
将两个子序列拷贝到缓冲区L[1:n1+1] R[1:n2+1]数组中
设置哨兵元素到多余的缓冲区末尾,供接下来的比较标识行尾
循环比较,将缓冲区内容按顺序搬运A