算法设计与分析电子教案.docx

上传人:b****8 文档编号:9281929 上传时间:2023-02-04 格式:DOCX 页数:108 大小:2.99MB
下载 相关 举报
算法设计与分析电子教案.docx_第1页
第1页 / 共108页
算法设计与分析电子教案.docx_第2页
第2页 / 共108页
算法设计与分析电子教案.docx_第3页
第3页 / 共108页
算法设计与分析电子教案.docx_第4页
第4页 / 共108页
算法设计与分析电子教案.docx_第5页
第5页 / 共108页
点击查看更多>>
下载资源
资源描述

算法设计与分析电子教案.docx

《算法设计与分析电子教案.docx》由会员分享,可在线阅读,更多相关《算法设计与分析电子教案.docx(108页珍藏版)》请在冰豆网上搜索。

算法设计与分析电子教案.docx

算法设计与分析电子教案

 

算法分析与设计教案

刘淑英

第一章基础

第二章分治与递归

第三章贪心法

第四章动态规划

第五章检索与周游

第六章回溯法

第七章分枝限界法

第一章基础

教学目的:

使学生了解课程的性质和任务,掌握集合的表示方法与操作算法。

教学重点:

使学生初步认识课程的性质与作用,激发课程学习热情。

教学难点:

理解集合表示的数据结构,掌握集合的操作算法设计。

1.1课程简介

1.2算法介绍

一、抽象问题类型

工程实例简介:

1)邮路问题;2)库存问题。

抽象化:

1)旅行商问题(TSP:

travelingsalesmanproblems)

n个城市,已知任意两个城市之间的距离。

从某个城市出发,经过余下的n-1个城市各一次,最后返回该城市,求所有可行路径[总共(n-1)!

条]中距离最短的一条路径。

2)0/1背包问题(knapsackproblems)

二、基本解题算法

穷举法,当不考虑约束条件时,可行解的总数

1)

2)O(2n)

可见,可行解的总数按指数规律增长。

三、课程任务

1)学习求解特定问题类型的有效算法(非数值计算问题)

抽象问题类型:

等价类问题,检索与周游,分类问题,最优化问题(背包问题,TSP问题,调度问题等),组合问题(n-皇后问题,子集和数问题,图着色问题等)。

算法设计方法:

分治法,贪心法,动态规划,回溯法,分支限界法,并行算法,递归与消除递归。

2)学习算法的表示方法

3)学习怎样分析算法的正确性

4)基本学会分析算法的效率

四、教学形式

讲授:

经典算法设计方法,针对抽象问题类的典型算法实例;

课外设计与上机:

编程上机实现经典问题的解题算法。

五、主要学习方法

课前预习,课堂听课与讨论,课后复习,大量的课外设计与上机编程实现。

六、考核方式

考查:

综合评价课堂学习态度、课堂讨论或回答问题的正确性、课外设计与上机、期末算法设计与编程联机考试等环节(公开题库,采用程序设计大赛形式)。

七、课程重要性

八、主要参考资料

[1]王晓东,算法设计与分析,北京:

清华大学出版社,2003.

[2]ThomasH.Cormen,CharlesE.Leiserson,RonaldL.Rivest,CliffordStein,算法导论,第二版影印版,北京:

高等教育出版社.

[3]严蔚敏,吴伟民,数据结构(C语言版),北京:

清华大学出版社,2003.

[4]BaaseS.andCelderA.V.,ComputerAlgorithm:

IntroductiontoDesignandAnalysis,thethirdedition,AddisonWesleyLongman,2000.

[5]HorowitzE.andSahniS.,FundamentalsofComputerAlgorithms,ComputerSciencePress,PitmanInc,1978.

[6]ShafferC.A.,DataStructureandAlgorithmAnalysis,Prentice-HallInc,中译本:

《数据结构与算法分析》,张铭、刘晓丹,电子工业出版社,1998.

[7]SartajShani,DataStructures,Algorithms,andApplicationsinC++,Prentice-HallInc,Homepage:

[8]KnuthD.E.著,管纪文译,《计算机程序设计技巧》,国防工业出版社,第一卷,1978,第二卷,1982.

[9]郭观七,甘靖,算法设计与分析实验指导书,自编,2006.

1.3集合的表示方法与操作算法

一问题

n个元素的集合U,可构造出许多互不相交的子集.例如

U={1,2,3,4,5,6,7,8,9,10},S1={1,7,8,9},S2={2,5,10},S3={3,4,6}

如何实现查找与并运算?

二集合的表示

1.位向量表示法

typedefstruct{typedefunion{

unsignedbit1:

1;struct{unsignedbit1:

1;

unsignedbit2:

1;unsignedbit2:

1;

……

unsignedbitn:

1;unsignedbitn:

1;}bits;

}SET;unsignedword[

];

}SET;

biti=

查找,并,交运算方法;

计算复杂性说明.

2.树结构表示法

用树结构表示的集合

集合的合并操作示意图

描述:

typedefstruct{

ElemTypedata;

inttag;/*根节点的值为负数,其它节点为指向父节点的指针*/

}ELEM;

ELEMset[n];/*初始化时每个集合元素与数组下标建立一对一映射关系*/

3.树结构表示法下集合操作算法

并操作:

voidU(inti,intj)

{

set[i].tag=j;

}

查找操作:

intF(inti)

{intj=i;

while(set[j].tag>=0)j=set[j].tag;

returnj;

}

n-1次并运算生成的退化树

计算复杂性分析:

并运算可能产生退化树;

并运算的计算复杂性为O

(1);

查找的计算复杂性可达O(n).

4.改进的操作算法

带加权规则的并操作:

如果集合i的元素少于集合j的元素,集合i合并到集合j,否则集合j合并到集合i.

实现方法:

根节点的tag域表示该集合的基数的负值,合并时根据集合的基数大小将小的集合合并到大的集合中,其算法为

voidunion(inti,intj)

{intsum=set[i].tag+set[j].tag;

if(set[i].tag>set[j].tag){set[i].tag=j;set[j].tag=sum;}

else{set[j].tag=i;set[i].tag=sum;}

}

利用加权规则得到的树

关于集合树的最大深度

引理1.3设T是一颗由算法union所产生的有n个节点的树,在T中没有节点的级数会大于

.

使用加权规则并运算产生的一棵最坏情况树

使用带加权操作的并运算后,并运算的计算复杂性为O

(1),查找算法的计算复杂性为O(logn).

压缩规则:

如果j是由i到它的根节点的路径上的一个节点,则置parent(j)=root(i), 带压缩规则的查找算法为:

intfind(inti)

{intt,j=i;while(set[j].tag>=0)j=set[j].tag;/*searchroot*/

while(i!

=j){t=set[i].tag;set[i].tag=j;i=t;}/*shorteningpath*/

returnj;

}

m次查找和n-1次并运算的计算复杂性:

引理1.3设T(m,n)是处理m≥n次find和n-1次union的混合序列所要求的最坏情况时间,则对于某两个正常数k1和k2有

实际上无论m,n增长多快,union-find的时间复杂度几乎与find的次数m成线性关系.

1.4小结

一个重点:

认识本课程的实用价值;

一个难点:

掌握集合的树结构表示和操作算法.

作业:

思考题:

p34.5~p34.9

第二章分治与递归

教学目的:

掌握应用递归实现分治的算法设计思想,基本掌握将递归算法改写成迭代算法的方法。

教学重点:

分治法和递归的问题求解思想,针对问题的经典分治算法。

教学难点:

将递归算法改写成迭代算法的一般方法。

2.1基本策略

一、求解大规模问题的复杂性

当问题的输入规模很大,直接求解非常困难,甚至不可能。

二、分治策略-化整为零、分别求解

将输入规模为n(n值很大)的问题,分解成k(1<k≤n=个与原问题有相同类型的子问题,分别求解k个子问题,将k个子问题的解以适当方式合并成原问题的解。

三、抽象的分治算法

设原问题的输入用外部数组a[n]表示,简记为(1,n);

子问题对应输入数据a[p]~a[q],简记为(p,q).

已知:

SOLUTION为表示问题的解的抽象数据类型;

intdivide(int,int);/*将问题进行分解的函数*/

intsmall(int,int);/*判断最小子问题的布尔函数*/

SOLUTIONconquer(int,int);/*求解最小子问题的函数*/

SOLUTIONcombine(SOLUTION,SOLUTION);/*合并子问题的解*/

 

抽象的分治算法可用下面的递归过程描述:

SOLUTIONDandC(p,q)/*divideandconquer*/

{if(small(p,q))returnconquer(p,q);

else{

m=divide(p,q);

returncombine(DandC(p,m),DandC(m+1,q));

}

}

对原问题求解,通过调用DandC(1,n)实现。

2.2二分检索

一、问题

n个按非降次序排列的元素a[n],查找元素x是否在表中出现,若找到,返回其下标值,否则,返回一负数.

原问题可表示为:

I=(n,a[0],…,a[n-1],x)

二、分治的基本思路

数据分组:

a[0]~a[k-2];

a[k-1];

a[k]~a[n-1].

对应于三个子问题:

I1=(k-1,a[0],…,a[k-2],x);

I2=(1,a[k-1],x);

I3=(n-k,a[k],…,a[n-1],x).

三、递归算法

设a[n]为外部数组,二分检索的递归算法可描述为

intBinSearch1(p,q,x)

{intk=(p+q)/2;

if(q

if(x==a[k])returnk;

if(x

if(x>a[k])returnBinSearch(k+1,q,x);

}

四、迭代算法

设a[n]为外部数组,二分检索的递归算法可描述为

intBinSearch2(n,x)

{intl=0,h=n-1,k;

while(l<=h)

{k=(l+h)/2;

if(x

elseif(x>a[k])l=k+1;

elsereturnk;

}

return–1;

}

 

五、计算复杂度分析

1.二元比较树

以有序表的中间元素为根节点的二分树,左子树上所有元素不比父节点元素值大,右子树上所有元素不比父节点元素值小.

例如,由元素1,2,3,4,5,6,7,8,9构成的有序表,对应的二元比较树

内节点,外节点------成功检索,不成功检索

二分检索树的深度k=

二元比较树的深度k=

2.时间复杂度

定理2.2若n在区域[2k-1,2k)中,则对于一次成功的检索,BinSearch至多作k次比较;而对于一次不成功的检索,或者作k-1次比较或者作k次比较。

成功检索最好情况:

O

(1)

不成功检索最好情况:

O(k)=O(

)=O(logn)

成功检索最坏情况:

O(k)=O(

)=O(logn)

不成功检索最坏情况:

O(k)=O(

)=O(logn)

平均情况分析:

内部路径长度之和I,外部路径长度之和E,E=I+2n。

成功检索的平均比较次数:

S(n)=(I/n)+1

不成功检索的平均比较次数:

U(n)=E/(n+1)

显然,S(n)=(1+1/n)U(n)-1,因为U(n)为O(logn),所以S(n)也为O(logn)。

成功检索不成功检索

最好最坏平均最好最坏平均

O

(1)O(logn)O(logn)O(logn)O(logn)O(logn)

3.以比较为基础检索的时间下界

定理2.3设a[n]含有n(n≥1)个不同元素,排序为a[1]<…

.

由此可见,任何以比较为基础的检索算法,最坏情况下的比较次数都不可能低于O(logn),因此,二分检索是最优的最坏情况算法.

2.3找最大和最小元素

一、问题

在含有n个不同元素的集合a[n]中同时找出它的最大和最小元素.

二、直接算法

StraitSearch(n,&max,&min)

{*max=*min=a[0];

for(i=1;i

{if(a[i]>max)max=a[i];

if(a[i]

}

}

比较次数2(n-1),若将语句1改写成

if(a[i]>max)max=a[i];

elseif(a[i]

最好情况n-1,最坏情况2(n-1),平均情况3/2(n-1).

三、实现分治策略的递归算法

●集合只有一个元素时

max=min=a[i]

●集合只有两个元素时

if(a[i]

else{max=a[i];min=a[j];}

●集合中有更多元素时

将原集合分解成两个子集,分别求两个子集的最大和最小元素,再合并结果.

●数据类型

typedefstruct{ElemTypemax,min;}SOLUTION;

●算法

SOLUTIONMaxMin(i,j)

{SOLUTIONs,s1,s2;

if(i==j){s.max=s.min=a[i];returns;}/*一元素*/

if(i==j-1)/*两元素*/

{if(a[i]

else{s.max=a[i];s.min=a[j];}

returns;

}

k=(i+j)/2;s1=MaxMin(i,k);s2=MaxMin(k+1,j);/*多元素时分治*/

(s1.max>=s2.max)?

(s.max=s1.max):

(s.max=s2.max);/*解的合并*/

(s1.min<=s2.min)?

(s.min=s1.min):

(s.min=s2.min);

returns;

}

●时间复杂度

令t(n)表示MaxMin需要的元素比较次数,存在下列递推关系

当n是2的幂时,即对于某个正整数k,n=2k,有

t(n)=2t(n/2)+2=2(2t(n/4)+2)+2=4t(n/4)+4+2

=2k-1t

(2)+

=2k-1+2k-2

=3n/2-2

注意:

当n是2的幂时,3n/2-2是最好、最坏及平均情况下的比较次数,与直接算法的最坏情况相比,少25%.

当元素的比较开销与整数比较开销相当时,将MaxMin的前两条if语句合并为:

if(i>=j-1)/*对应一元素和两元素的情况*/

{if(a[i]

else{s.max=a[i];s.min=a[j];}

returns;

}

MaxMin需要的比较次数,存在下列递推关系

比StraitSearch算法的3(n-1)低.但MaxMin需要更多存储空间和更多的堆栈操作,实际效率可能更低。

四、结论

当元素的比较开销比整数比较开销大得多时,MaxMin算法比StraitSearch算法效率高,反之,效率低.因此,分治策略只能看成是一个较好的但并不总是真正好的设计策略。

思考题:

1.请分析和证明E=I+2n。

2.请分析c(n)递推关系式中常数3为什么是3而不是2?

2.4分类

一、问题

给定一个含n个元素的集合a[n],按一定次序(本课程假定均为非降次序)将其分类(排序).

二、插入分类

●原理

已分类的部分

未分类的部分

a[1]

a[j-1]

a[j]

a[j+1]

a[n]

将未分类的元素逐个插入到已分类部分的正确位置上.

●插入分类算法

InsertSort(intn)

{for(j=1;j

{for(unsorted=a[j],k=j-1;(k>=0)&&(unsorted

a[k+1]=a[k];

a[k+1]=unsorted;

}

}

●时间复杂度

考虑内层for循环中元素比较的次数T(n):

最坏情况T(n)=

=1+2+…n-1=

=O(n2)

最好情况T(n)=O(n)

 

三、归并分类

●原理

a[low]

a[

]

a[

]

a[high]

归并分类

归并分类

按非降次序合并两个已分类的子集

●归并分类的递归算法

MergeSort(low,high)

{if(low

{mid=(low+high)/2;MergeSort(low,mid);MergeSort(mid+1,high);

Merge(low,mid,high);

}

}

●已分类子集的归并过程示例

A

1

3

4

5

6

9

10

2

7

8

11

12

13

14

指针

L=1,K=1,H=8

B

1

指针

L=2,H=8,K=2

B

1

2

指针

L=2,H=9,K=3

B

1

2

3

4

5

6

指针

L=5,H=9,K=7

B

1

2

3

4

5

6

7

8

指针

L=5,H=11,K=9

B

1

2

3

4

5

6

7

8

9

10

指针

L=8,H=11,K=11

B

1

2

3

4

5

6

7

8

9

10

11

12

13

14

指针

L=8,H=15,K=15

Merge(low,mid,high)

{ElemTypeb[n];l=low;h=mid+1;k=l;

while((l<=mid)&&(h<=high))/*部分合并*/

{if(a[l]<=a[h])b[k++]=a[l++];

elseb[k++]=a[h++];

}

if(l>mid)while(h<=high)b[k++]=a[h++];/*转储余下部分*/

elsewhile(l<=mid)b[k++]=a[l++];

a[low:

high]=b[low:

high];/*将b数组转储到a*/

}

●时间复杂度

设归并分类的时间复杂度为T(n),存在递归关系:

●缺点与改进方法

四、比较为基础的分类算法的时间下界

结论:

以比较为基础的分类算法在最坏情况下的时间下界为O(nlogn),是最坏情况下的最优算法.

五、快速分类

●原理

a[1]

a[j-1]

a[j]

a[j+1]

a[n]

使a[1:

j-1]≤a[j]

a[j]

使a[j+1:

n]≥a[j]

对a[1:

j-1]快速分类

a[j]

对a[j+1:

n]快速分类

已分类的集合

●实现部分分类的划分过程举例

原始

4

1

3

6

2

5

7

8

指针

r=4

j

k

一次循环

r=4

j

k

r=4

1

3

2

6

5

7

8

二次

循环

k

j

交换位置

2

1

3

r=4

6

5

7

8

k

●实现部分分类的划分算法

Partition(p,q)

{r=a[p];j=p+1;k=q;

while

(1)

{while((j<=k)&&(a[j]<=r))j++;

while((j<=k)&&(a[k]>=r))k--;

if(j

elsebreak;

}

a[p]=a[k];a[k]=r;

returnk;

}

●快速分类算法

QuickSort(p,q)

{if(p

{j=Partition(p,q);

QuickSort(p,j-1);

QuickSort(j+1,q);

}

}

●时间复杂度

快速分类算法的计算时间C(n)取决于Partition的元素比较次数.

在最坏情况下(划分元素取第一个元素),每级Partition(p,q)调用,最多作p-q+1次元素比较,因此,Cw(n)=n+n-1+…+2=O(n2).

在平均情况下,假设:

n个元素各不相同,划分元素随机选取,取第k(1≤k≤n)个元素是等概率的,因此,存在下列递归关系:

(1)

(2)

用n-1替换

(2)中的n,得:

(3)

(2)-(3)得:

nCA(n)-(n-1)CA(n-1)=2n+2CA(n-1)

即:

CA(n)/(n+1)=CA(n-1)/n+2/(n+1)(4)

反复用(4)替换CA(n-1),CA(n-2),…,得到:

CA(n)/(n+1)=CA

(1)/2+

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 小学教育 > 小升初

copyright@ 2008-2022 冰豆网网站版权所有

经营许可证编号:鄂ICP备2022015515号-1