《算法导论》复习大纲DOC.docx
《《算法导论》复习大纲DOC.docx》由会员分享,可在线阅读,更多相关《《算法导论》复习大纲DOC.docx(68页珍藏版)》请在冰豆网上搜索。
《算法导论》复习大纲DOC
《算法设计与分析》复习提纲2014.7.5
1引言(ch1)
1.什么是算法及其特征
算法(Algorithm)是通过一个有限的指令序列集合对特定问题进行求解的一种计算执行描述。
算法特征:
(1)输入:
一个算法具有零个或多个取自指定集合的输入值;
(2)输出:
对每一次输入,算法具有一个或多个与输入值相联系的输出值;
(3)确定性:
算法的每一个指令步骤都是明确的;
(4)有限性:
对每一次输入,算法都必须在有限步骤(即有限时间)内结束;
(5)正确性:
对每一次输入,算法应产生出正确的输出值;
(6)通用性:
算法的执行过程可用于所有同类求解问题,而不仅适用于特殊输入。
2.问题实例和问题规模
问题实例是指需要计算同一个结果的问题的所有输入。
问题规模是指输入实例的大小,而输入实例是指问题的具体计算例子
2算法初步(ch2)
1.插入排序算法
1)算法步骤:
从左到右扫描数据A,扫描到一个元素,将A[j]与其左边的元素从右到左依次比较,若比之小,则将其之前元素后移,插入A【j】,直至A【j】比他前面的元素大,扫描A中的下一个元素
2)伪代码:
InsertSort(A)
{
forj=2toA.length//第一层循环
{
Key=A[j]
i=j-1
Whilei>0anda[i]>key//第二层循环
{
A[i+1]=A[i]
}
i=i-1
A[i+1]=key
}
}
2.算法复杂性及其度量
(1)时间复杂性和空间复杂性;
(2)最坏、最好和平均情形复杂性;
顺序情况下B(n)=O(n)、倒序情况下W(n)=O(n2)、A(n)=O(n2)空间复杂性:
需要常数个额外的临时空间存储临时数据
2.插入排序的最坏、最好和平均时间
最坏O(n2)、最好O(n)和平均时间O(n2),空间复杂度是O
(1),稳定排序
3.归并排序算法及其时间复杂性-时间Θ(nlogn))
1)算法步骤
分解:
分解待排序的n个元素的序列为各具n/2个元素的两个子序列
解决:
适用归并排序递归的排序2个子序列
合并:
从左到有遍历2个子序列,比较最前面的元素,将较小的元素移出子序列合并到上级序列的末尾,循环进行上2步,直接所有元素都被合并到上级序列,公进行r-p+1次;
2)伪代码:
MERGE-SORT(A,p,r)
{
ifpq=向下取整(p+r)/2
MERGE-SORT(A,p,q);
MERGE-SORT(A,q+1,r)
MERGE(A,p,q,r)
}
MERGE(A,p,q,r)
{
N1=q-p+1
N2=r-q
将A拆成长度分别为N1、n2的2个子数组L,R
L,R的末尾元素的后一个元素取值无穷大,作为哨兵;
i=1,j=1
fork=ptor
ifL[i]<=R[j]
A[k]=L[i]
i=i+1
else
A[k]=R[j]
j=j+1
}
3函数增长率(ch3)
1.渐近记号O、Ω、θ的定义及其使用
1)O
渐进上界:
0<=f(n)<=C(g(n))
当n->∞,f(n)的阶小与g(n)的阶
2)Ω
渐进下界:
0<=C(g(n))<=f(n)
当n->∞,f(n)的阶大与g(n)的阶
3)Θ
渐紧界:
0<=C1(g(n))<=f(n)<=C2(g(n))
当n->∞,f(n)的阶与g(n)的阶相等
2.标准复杂性函数及其大小关系
(1)多项式时间阶的大小
O
(1)(2)指数时间阶的大小
O(2n))3.和式界的证明方法
1)数学归纳法
猜测解->证明
2)对象限界
最大最小项限界;几何级数限界;
3)和式分解
简单的一分为二;更复杂的划分;积分近似;
4)Knuth求和:
使用数学归纳法;使用摄动法;使用递归;使用积分;使用二重求和;使用有限演算;使用母函数。
4递归关系式(ch4)
1.替换法
(1)猜测解数学归纳法证明;
T(n)=2T(⌊n/2⌋)+n
猜:
T(n)=O(nlogn)
证:
2T(⌊n/2⌋)+n<=Cnlogn带入计算
(2)变量变换法;
T(n)=2T(⌊n1/2⌋)+logn
令m=logn,则,n=2m
T(2m)=2T(⌊2m-1/2⌋)+m,
令S(m)=T(2m)
则:
S(m)=2S⌊m/2⌋+m类似T(n)=2T(⌊n/2⌋)+n
=O(mlogm)
=O(lognloglogn)
2.迭代法
(1)展开法;
T
(1)=O
(1)
T(n)=3T(⌊n/4⌋)+n=n+3⌊n/4⌋+32⌊n/42⌋+…+3KT(n/4K)
总有K,使得1=(2)递归树法;
T(n)=T(n/3)+T(2n/3)+n
T(n)=2T(n/2)+n2
●主定理
T(n)=aT(n/b)+f(n)a>=1,b>=1整数
Case1f(n)=O(nlogba-Ɛ)<=Cnlogba-Ɛ则:
T(n)=Θ(nlogba)
Case2f(n)<=Θ(nlogba)则:
T(n)=Θ(nlogba*logn)
Case3f(n)=Ω(nlogba-Ɛ)>=Cnlogba+Ɛ且:
af(n/b)<=cf(n),对于常数C<=1和足够大的n成立,
则T(n)=Θ(f(n))
5堆排序(ch6)
1堆的概念和存储结构
堆是一种数据结构,堆是一个数组,近似完全二叉树,除最底层外,全部从左到右填充满,对于序号为i的结点,其父结点的序号为i/2,其左孩子的序号为2i,其右孩子序号为2i+1;
0<=A.heap-size<=A.length
n个元素的序列{k1,k2,ki,…,kn}当且仅当满足下关系时,称之为堆。
(ki <=k2i,ki <=k2i+1)或者(ki >=k2i,ki >=k2i+1),(i=1,2,3,4...n/2)
●堆的性质和种类
大根堆:
除根结点外,所有结点小于其父结点;用于堆排序、收益问题。
小根堆:
除根结点外,父结点小于其所有结点;用于优先队列;成本问题;
●堆的操作:
建堆;整堆;
1)整堆算法:
假设i的左右子树已经是大根堆,对i结点进行整堆,使其也是大根堆
对调整的子树结点循环进行上2步骤,将小元素逐级下沉,直至满足堆特性;
整堆时间复杂度O(logn)
2)整堆伪代码
Max-heapify(A,i)
{l=left(i)
r=right(i)
iflA[i]
largest=l
elselargest=i
ifrA[i]
largest=r
iflargest<>i
exchangea[i]withlargest
max-heapify(A,largest)
}
3)建堆算法
因为从A.heap-size/2+1起到A.heapsize,都是叶子结点,故建堆可从A.heap-size/2起到1整堆实现;算法复杂度O(n)
4)建堆伪代码
Bulid_max_heap(A)
{
heap-size=A.length
fori=⌊A.heap-size/2⌋to1
Max-heapify(A,i)
}
●堆排序算法和时间复杂性
算法思想:
1)将数组建堆
2)将根元素与结点n交换并缩减堆的长度1
3)对首元素整堆
4)重复上述3个步骤,直至堆大小为1(i=2时进行最后一次重复操作)
时间复杂度O(nlgn)
伪代码
Heapsize(A)
{
build_max_heap(A)
Fori=A.lengthto2
ExchangeA[1]toA[i]
A.heap-size=A.heap-size-1
max-heapfly(A,1)
}
●优先队列及其维护操作
优先队列是维护集合S的数据结构,每个元素具有一个关键字key;用于分支限界、搜索算法。
支持如下操作:
a)插入insert(S,x)
算法思想:
1)将元素插入末尾Size+1的位置
2)从插入位置自底而上调整,使之满足堆性质
算法复杂度O(logn)
b)取最大关键字Maximum(S)
算法思想,输出优先级最大的,也就是堆的根元素;
c)删除并返回最大键值的元素Extract-max(S)
算法思想:
1)取堆根
2)A[1]<-A[heap-size[A]]
3)heap-size[A]——
4)对A[1]整堆
时间复杂度O(logn)
d)增值元素x的关键字增加到kIncrease-Key(S,x,k)
算法思想:
1)如果A[i]的关键字大于K,则对i进行整堆;
2)否则,若i不是根结点且K大于A[i]的父结点,则交换A[i]与其父结点的关键字,并将K值赋予其父结点。
时间复杂度O(logn)
6快速排序(ch7)
1.快速排序算法及其最好、最坏时间和平均时间
快排采用分治法的思想,最好O(nlogn),最坏O(n2),平均O(nlogn)
(1)分治法的基本思想
分治法的基本思想是:
将原问题分解为若干个规模更小但结构与原问题相似的子问题。
递归地解这些子问题,然后将这些子问题的解组合为原问题的解。
(2)快速排序的基本思想
设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解:
在R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos-1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无须参加后续的排序。
A[p..r]被划分为俩个(可能空)的子数组A[p..q-1]和A[q+1..r],使得
A[p..q-1]<=A[q]<=A[q+1..r]
②求解:
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
3合并
//快速排序
voidquick_sort(ints[],intl,intr)
{
if(l{
inti=l,j=r,x=s[l];
while(i{
while(i=x)//从右向左找第一个小于x的数
j--;
if(is[i++]=s[j];
while(ii++;
if(is[j--]=s[i];
}
s[i]=x;
quick_sort(s,l,i-1);//递归调用
quick_sort(s,i+1,r);
}
}
2.随机快速排序算法及其期望时间
期望时间负责度O(nlogn)
算法描述:
分解:
以a[p]为基准元素将a[p:
r]划分为3段a[p:
q-1],a[q]和a[q+1:
r],使a[p:
q-1]中任何一个元素小于等于a[q],而a[q+1:
r]中任何一个元素大于等于a[q]。
下标q在划分过程中确定。
递归求解:
通过递归调用快速排序算法分别对a[p:
q-1]和a[q+1:
r]进行排序。
合并:
由于对a[p:
q-1]和a[q+1:
r]的排序是就地进行的,所以在a[p:
q-1]和a[q+1:
r]都已排好的序后,不需要执行任何计算,a[p:
r]就已排好
voidRandomizedQuickSort(double*a,intbegin,intend)//随机化快速排序
{
if(begin{
intp=RandomizedPartition(a,begin,end);
RandomizedQuickSort(a,begin,p-1);
RandomizedQuickSort(a,p+1,end);
}
}
intRandomizedPartition(double *a,intbegin,int end)
{ int i=Random(begin,end);
double temp = a[end];
a[end]=a[i];
a[i]=temp;
return Partition(a,begin,end);
}
intRandom(intm,intn)//产生一个随机下表,用其对应的数组元素作为比较标准
{
srand((unsigned)time(NULL));
returnm+(rand()%(n-m+1));
}
intPartition(double*a,intbegin,intend)
{
inti=begin-1,j=begin;
doublex=a[end];
while(j{
if(a[j]<=x)
{i++;
doubletemp=a[i];
a[i]=a[j];
a[j]=temp;
}
j++;
}
doubletemp=a[end];
a[end]=a[i+1];
a[i+1]=temp;
returni+1;
}
7线性时间排序(ch8)
1.基于比较的排序算法下界:
Ω(nlogn)
证明:
设h、l分别代表判断树的高度和叶子树
∵判定树是一颗二叉树
∴l≤2h//叶子数不超过2h
∴n!
≤l≤2h//n!
为排序的结果数
于是有,h≥logn!
≥Ω(nlogn)证毕!
2.计数排序适应的排序对象、算法和时间
基本思想:
统计小于或等于A[i]的元素数目,将A[i]置入相应的位置,即
A[i]->B[小于或等于A[i]的元素数目]
主要要解决的问题:
Ø计数:
统计小于或等于统计小于或等于A[i]的元素数目
Ø值相同元素的处理
一种特殊情形的计数排序:
问题:
n个互不相同的整数A[1..n],1≤A[i]≤n,i=1~n
排序算法:
SpecialCountingSort(A,B)
{//B[1..n]为排序结果
fori←1tondo
B[A[i]]←A[i];//如A[i]=5,就放到B[5]中
}
时间:
O(n),无比较
一般情形的计数排序:
问题:
n个可以相同的整数A[1..n],1≤A[i]≤k,i=1~n,这里k是A[i]的取值范围,不一定为n。
基本思想:
步骤:
A[1..n]→计数器C[1..k]→B[1..n]
ØStep1(值相同元素的计数值相同元素的计数):
将A中的值为i的元素个数记入C[i]中;
ØStep2(累计计数):
对C[1..k]进行修改,使得C[i]的值表示为≤i的元素个数;
ØStep3(放置):
将A[j]依据C[A[j]],放入正确位置B[C[A[j]]]上,并修改C[A[j]]←C[A[j]]-1;
算法:
CountingSort(A,B,k)
{//B[1..n]为排序结果,C[1..k]为计数数组
fori←1tokdoC[i]←0;
forj←1tolength[A]do//扫描A,值相同元素计数值相同元素计数
C[A[j]]++;
fori←2tokdo//C[i]修改,累计计数
C[i]←C[i]+C[i-1];
forj←length[A]downto1do
{
B[C[A[j]]]←A[j];
C[A[j]]--;
}
}
时间:
T(nk)=θ(n+k)=θ(n)如果k=θ(n)时
3.基数排序适应的排序对象、算法和时间
假定A[1..n]是非负整数,用k进制表示为不超过d位数。
算法:
RadixSort(Ad)RadixSort(A,d)
{
fori←1toddo
使用稳定的排序算法对使用稳定的排序算法对A的第i位排序;//如计数排序
}
时间:
T(n)=θ(d(n+k))//k为基,d为位数
=θ(n)//如果k=θ(n)且d是常数
示例:
引理8.3,给定n个d位数,其中每一个数位有k个可能的取值。
如果RADIX-SORT使用的稳定排序方法耗时θ(n+k),那么它就可以在θ(d(n+k))时间内将这些数排好序。
证明:
当每位数字都在0到k-1区间内(这样它就有k个可能的取值),且k的值不太大的时候,计数排序是一个好的选择。
对n个d位数来说,每一轮排序耗时θ(n+k)。
共有d轮,因此基数排序的总时间为θ(d(n+k)).
d不为常数,基数排序算法还是线性时间吗?
设n个整数的取值范围是0~nc,c是整常数,c≥1
对于十进制整数,nc需要的位数d=⌊log10nc⌋+1≈log10n
∴T(n)=θ(d(n+k))=θ(nlogn)//k为10
因此,不是线性时间排序
算法何时为线性时间?
Idea:
只要使d变为常数,k变大到与n同阶
HowtodoHowtodo:
选基k=n,则nc的位数为lognnc=c=d
∴d=c,k=n
∴T(n)=θ(n)
4.桶排序适应的排序对象、算法和时间
假定:
输入是均匀分布在[0,1)上的实数。
基本思想:
①[0,1)划分为[0,1/n),[1/n,2/n),…,[k/n,(k+1)/n),…,[(n-1)/n,1)n个大小相等的子区间,每个子区间看作一个桶;
②将n个元分配桶中;
③对每个桶里的元素进行排序,依次连接桶;
输入:
0≤A[1..n]<1
辅助数组:
B[0..n-1]是一个指针数组,指向每个桶(链表)
关键字映射:
由于0≤A[i]<1,必须将A[i]映射到0,1…n-1上
∵[0,1)→[0,n)//通过函数nA[i]
即k≤nA[i]<k+1//存在k
∴桶号k=⌊nA[i]⌋//映射函数
算法描述:
BucketSort(A)
{
n←length[A];Time
fori←1tondo//扫描Aθ(n)
将A[i]插入到链表B[⌊nA[i]⌋]中;
fori←0ton-1doθ(n)*
用插入排序将B[i]排序;
将B[0],B[1],…,B[n-1]连接起来;θ(n)
}
注:
∵n个数是均匀分布在[01)中,
∴每个桶中大约只有一个数,
∴时间为O
(1)
8中位数和顺序统计(ch9)
1.最大和最小值的求解方法
最小/最大值:
最坏情形W(n)=n-1次比较,时间为θ(n)
同时求最大、最小值
Ø一种方法:
独立分别求,比较次数为n-1+n-2=2n-3
Ø另一种方法:
成对输入x,y,每对比较3次
①比较x,y;
②将min(x,y)与当前最小值比较;
③将max(x,y)与当前最大值比较;
总比较次数约为3⌊n/2⌋。
//第一对元素比较一次,最后一组元素若为一个,至多比较二次
2.期望时间为线性的选择算法
基于分治法的思想:
利用快排序的随机划分法,进行问题的划分
具体步骤:
1 划分A[p..r]=>A[p..q-1]≦A[q]2 K<-q-p+1;//即A[q]是第k个最小元
3 If(i=k)then//k=左区间长度+1
returnA[q];
If(iIf(i>k)then在右区间中继续找第i-k个元素;
临界条件:
当区间长度为1时,直接返回该元素
RandomizedSelect(A,p,r,i)
{//选择ith元素
ifp=rthenreturnA[p];//临界问题处理
q←RandomizedPartition(A,p,r);//进行划分并返回划分元的下标
k←q-p+1;//A[q]是第k个小的元素
ifi=kthen//A[q]是ith元素
returnA[q];
elseifi<kthen//ith元素落在左区间
returnRandomizedSelect(A,p,q-1,i);
else//ith元素落在右区间
returnRandomizedSelect(A,q+1,r,i-k);
}
最好:
每次划分为相等的左右区间T(n)=T(n/2)+n=>T(n)=θ(n)
最坏:
每次划分为不均等的左右区间T(n)=T(n-1)+n=>T(n)=θ(n2)
平均(期望):
分析略。
T(n)=θ(n)
3.最坏时间为线性的选择算法及其时间分析
算法步骤:
Whilen>1do
step1.将n个元素分成5个1组,共⌈n/5⌉组。
其中最后1组有nmod5个元素。
step2.用插入排序对每组排序,取其中值。
若最后1组有偶数个元素,取较小的中值。
step3.递归地使用本算法找找⌈n/5⌉个中值的中值x。
step4.用x作为划分元对A数组进行划分,并设x是第k个最小元。
step5.ifi=kthenreturnx;
elseifielse找右区间的第i-k个最小元;
n个元素中至少有多少个元素>x?
大于x的元素至少有3(⌈⌈n/5⌉/2⌉-2)≥3n/10-6
同理,小于x的元素至少有3n/10-6
由上=>左区间和右区间的最大长度≦7n/10+6
运行时间递归式的建立
step12:
O
(1);
step3:
T(⌈n/5⌉);
step4:
O(n);
step5:
至多T(7n/10+6)
(n/5向上取整)
运行时间递归式的求解
用替代法证:
T()n)≤cn
T(n)≤c⌈n/5⌉+c(7n/10+6)+an//a为常数
≤c(n/5+1)+c(7n/10+6)+an
=cn/5+c+7cn/10+6c+an
=9cn/10+7c+an
=cn+(-cn/10+7c+an)
≤cn//if-cn/10+7c+an≤0
要使-cn/10+7c+an≤0,只要c≥10an/(n-70)
∵假定n>140,∴有n/