大连理工大学算法与设计算法讲解Word下载.docx
- 文档编号:18623077
- 上传时间:2022-12-29
- 格式:DOCX
- 页数:30
- 大小:962.76KB
大连理工大学算法与设计算法讲解Word下载.docx
《大连理工大学算法与设计算法讲解Word下载.docx》由会员分享,可在线阅读,更多相关《大连理工大学算法与设计算法讲解Word下载.docx(30页珍藏版)》请在冰豆网上搜索。
2..现在只需要证明,当添加的边其中有一个顶点是v的情形成立即可。
假设其余k个结点为uk(k=1,2,3….)其中W(U1v)最小。
任意连接Uk(k=2,3…..),一定会出现一条回路。
因为采用的是Prim算法,切V结点是最后一个加入进来的,因此回路中不存在大于W(U1V)或者大于W(UkV)的边,并且W(UkV)>
W(U1V),所以加入的UkV是回路中权值最大的边,符合MST性质,因此,这种情形下,n=k+1成立
综上所述,prim算法正确。
3..写出一个怎样找到一个图中的割点的算法描述。
由于上述算法是一个遍历的过程,因此求关键点的事假复杂度为O(n+e).
4.n个节点的二叉树有多少棵?
给出证明。
可以分析,当n=1时,只有1个根节点,则只能组成1种形态的二叉树,令n个节点可组成的二叉树数量表示为h(n),则h
(1)=1;
h(0)=1;
当n=2时,1个根节点固定,还有2-1个节点。
这一个节点可以分成(1,0),(0,1)两组。
即左边放1个,右边放0个;
或者左边放0个,右边放1个。
即:
h
(2)=h(0)*h
(1)+h
(1)*h(0)=2,则能组成2种形态的二叉树。
当n=3时,1个根节点固定,还有2个节点。
这2个节点可以分成(2,0),(1,1),(0,2)3组。
即h(3)=h(0)*h
(2)+h
(1)*h
(1)+h
(2)*h(0)=5,则能组成5种形态的二叉树。
以此类推,当n>
=2时,可组成的二叉树数量为h(n)=h(0)*h(n-1)+h
(1)*h(n-2)+...+h(n-1)*h(0)种,即符合Catalan数的定义,可直接利用通项公式得出结果。
令h
(1)=1,h(0)=1,catalan数(卡特兰数)满足递归式:
h(n)=h(0)*h(n-1)+h
(1)*h(n-2)+...+h(n-1)h(0)(其中n>
=2)
该递推关系的解为:
h(n)=C(2n,n)/(n+1)(n=1,2,3,...)
5.给出利用DFS进行拓扑排序算法描述,并给出时间复杂度分析
把图中节点的状态分成三种。
white代表节点还未被搜索到,gray代表节点已被搜索到但还未被处理完,black代表节点已被处理完。
数组topo[]来记录每个顶点的编号。
把图中所有的节点的状态初始化为white,topoNum=n,从顶点号为1的顶点开始搜索color[1]=gray.
设当前搜索到的节点为v,则按深度优先的方式搜索它的邻接点,若存在某个邻接点状态为white,则把该邻接点的状态改为gray,把它作为当前搜索到的节点,继续按深度优先方式搜索;
若所有的邻接点状态都不是white则把当前节点状态改为black,topo[v]=topoNum,topoNum--,然后退回到上一个节点。
当所有节点的状态都为black时,退出循环。
设顶点数为n,边数为m。
算法分为两部分:
初始化和搜索节点,显然初始化的时间复杂度是O(n),搜索节点则是按按深度优先的方式查找所有的边,时间复杂度为O(m+n),故此时间复杂度为O(m+n)。
6.对于给定的长度为n的数字序列,给出一个算法,找到该序列中的最长不降子序列(要求至少找到一个)。
即对于序列a1,a2,a3,……,an,找到一组1<
=j1<
j2<
……<
jk<
=n,使得aj1<
=aj2<
=……<
=ajk,且k最大。
并分析时间复杂度
解答:
定义两个数组maxLength[n]和preEle[n]
maxLength[i]表示:
序列a1,a2,a3,……,ai中,ai之前(包括ai)最长的子序列的长度
preEle[i]表示:
上诉子序列中ai的前一个元素的编号。
初始:
maxLength[1]=1,preEle数组全部置0
for(intk=2;
k<
=n;
k++)
{//对于a1,a2,a3,……,ak-1中小于ak的所有at所对应的maxLength[t]中找到最大的一个,将该maxLength[t]加上1即为maxLength[k],找到的t即为at在当前最长不下降子序列中的前一个元素
maxLength[k]=max{maxLength[t]|1<
=t<
k,at<
=ak}+1;
preEle[k]=上式中找到的t;
}
最后,maxLength[n]数组中最大的数即为所求的最长不下降子序列的长度,对应的元素即为最长不下降子序列的最后一个元素,从此元素开始,顺着该元素对应的preEle数组元素向前找对应的元素,直到找到的元素对应的preEle数组元素为0,便得到所求序列。
时间复杂度分析:
为了获得每个元素ai对应的数组元素maxLength[i]的取值,都需要对原序列中ai之前的每个数进行检验,故时间复杂度为O(n2)。
举例:
数字序列:
192385106
找到的maxLength数组中最大的元素为maxLength[7]和maxLength[8],所以找到两个所求的序列,分别为:
1,2,3,5,6
1,2,3,5,10
7.已知一有向图G=(V,E),其每条边(u,v)∈E均对应有一个实数值r(u,v),表示从顶点u到顶点v之间的通信线路的可靠性,取值范围为0≤r(u,v)≤1,定义r(u,v)为从u到v的线路不中断的概率,并假定这些概率是相互独立的。
写出一个有效算法,来找出两个指定顶点间的最可靠的线路。
运用Dijkstra算法的思想,将原来的加法计算改为乘法即可。
例如下图:
解答过程如下:
每一行的意义:
从A出发,经过所用可能路径,
到达各点的最可靠效率
第一次找到B之后,就不用再找了,
因为再乘以任何r(u,v)([0-1])
会使得A到B的可靠性减小
8.Floyd算法求出任意两点间的最短距离。
例:
有向图中有四个点,点之间的距离如下所示:
for(k=0;
k<
n;
k++)
for(i=0;
i<
i++)
for(j=0;
j<
j++)
A[i,j]=min{A[i,j],A[i,k]+A[k,j]}
算法思想:
从图的带权邻接矩阵A=[a(i,j)]n×
n开始,
递归地进行n次更新,即由矩阵D(0)=A,
按一个公式,构造出矩阵D
(1);
又用同样地公式由D
(1)构造出D
(2);
最后又用同样的公式由D(n-1)构造出矩阵D(n)。
矩阵D(n)的i行j列元素便是i号顶点到j号顶点的最短路径长度
9.对于矩阵乘法:
第1个乘号第(n-1)个乘号
A1×
A2×
…×
An
d0×
d1d1×
d2dn-1×
dn
给出每个乘法运算的执行顺序,使得进行整个矩阵乘法运算过程中进行的数值乘法次数最少。
定义函数cost(low,high),表示计算矩阵A(low)×
…×
A(high)所需的最少数值乘法次数,root(low,high)表示相应于上述cost(low,high)的进行的最后一次乘法的位置。
则状态转移方程为:
当low==high时,cost(low,high)=0,root(low,high)=-1
当low<
high时,
cost(low,high)=min{cost(low,k)+cost(k+1,high)+d(low-1)×
dk×
d(high)|low<
=k<
=high-1}式
(1)
root(low,high)=k(式
(1)中的k)
伪代码实现:
定义两个二维数组cost[1...n][1…n]和root[1…n][1…n]
//初始化数组的对角线元素
for(i=1;
i<
i++)
cost[i][i]=0;
root[i][i]=-1;
//按一定的顺序填充数组
for(low=n-1;
low>
=1;
low--)
for(high=low+1;
high<
high++)
cost[low][high]=maxNum;
//maxNum表示无穷大
for(k=low;
high;
k++)//计算选取不同乘号进行最后一次乘法运算的代价
if(cost[low][k]+cost[k+1][high]+dlow-1×
dhigh<
cost[low][high])
cost[low][high]=cost[low][k]+cost[k][high]+dlow-1×
dhigh;
root[low][hith]=k;
最终,cost[1][n]即为进行该矩阵乘法所需的最少代价。
对root数组进行如下的后序遍历,即可得到代价最少的乘法次序,乘法进行的次序存储在数组multOrder[]中
intmultOrderNext;
extractOrderWrap(intn,introot[],multOrder[])
{
multOrderNext=1;
extractOrder(1,n,multOrder);
extractOrder(intlow,inthigh,introot[],intmultOrder[])
Intk;
If(low<
high)
k=root[low][high];
extractOrder(low,k,multOrder);
extractOrder(k+1,high,multOrder);
multOrder[multOrderNext]=k;
multOrderNext++;
A1×
A3×
A4
30×
11×
4040×
1010×
25
d0×
d1d1×
d2d2×
d3d3×
d4
注:
以下cost[i][j]用Cij表示,root[i][j]用Rij表示
C11=C22=C33=C44=0
C12=C11+C22+30×
1×
40=1200
R12=1
C23=C22+C33+1×
40×
10=400
R23=2
C34=C33+C44+40×
10×
25=10000
R34=3
C13=C11+C23+30×
10=700ok
C12+C33+30×
10=13200
R13=1
C24=C22+C34+1×
25=11000
C23+C44+1×
25=650ok
R24=3
C14=C11+C24+30×
25=1400ok
C12+C34+30×
25>
1400
C13+C44+30×
R14=1
所以最小代价C14=1400
10.给定长度为n的有序元素序列K1,K2,…,Kn,其各个元素被查找的概率(或频率)分别为p1,p2,…,pn。
描述构造最优二分树的算法
定义函数cost(low,high),表示用K(low)…K(high)构造得到的最优二分树的总代价,root(low,high)表示相应二分树的树根位置。
当low>
high(low=high-1)时,
令cost(low,high=0)
root(low,high)=-1
=high时,
cost(low,high)=p(low)+…+p(high)+min{cost(low,k-1)+cost(k+1,high)|low<
=high}式
(1)
root(low,high)=k(式
(1)中对应cost(low,high)的k)
定义两个二维数组cost[1...n+1][0…n]和root[1…n+1][0…n]
//初始化数组的对角线元素,即(t+1,t)
=n+1;
cost[i][i-1]=0;
root[i][i-1]=-1;
for(low=n;
for(high=low;
//maxNum表示无穷大
=high;
k++)//选取不同的元素作为当前树的树根
currentCost=low…high的概率和+cost(low,k-1)+cost(k+1,high)
if(currentCost<
cost[low][high]=currentCost;
root[low][high]=k;
最终,cost[1][n]即为最优二分树的代价。
对root数组进行先序遍历,即可得到最优二分树。
C10=C21=C32=C43=C54=C65=C76=0
R10=R11=R22=R33=R44=C65=C76=-1
C66=C65+C76+2=2OKR66=6
C55=C54+C65+1=1OKR55=5
C56=C54+C66+3=5
C55+C76+3=4OKR56=6
C44=C43+C54+7=7OKR44=4
C45=C43+C55+8=9OKR45=4
C44+C65+8=15
C46=C43+C56+10=14OKR46=4
C44+C66+10=19
C45+C76+10=19
以下省略.......
C16=C10+C26+25=63
C11+C36+25=52OKR16=2
最优二分树的建立
root[1][6]=2,所以2为树根,左子树有1,右子树有3-6;
root[3][6]=4,所以4为树根,左子树有3,右子树有5-6;
root[5][6]=6,所以6为树根,左子树有5,右子树为空
最后构成的最优二分树如图:
11.给出一个比较好的最大最小元算法。
基于思想:
对策论
两两结组,选出winner和loser。
winner里面找到最大的。
loser里面找到最小的。
具体分析:
元素个数n为偶数时:
结组比较:
n/2次;
在n/2个winner中找到最大元:
n/2-1;
在n/2个loser中找到最小元:
比较次数:
C=(3n-4)/2;
元素个数n为奇数时(添加元素a[n]=a[n-1]):
n-1/2次;
在n-1/2个winner中找到的最大元和a[n]选出最大元:
(n-1/2)-1+1;
在n-1/2个loser中找到的最小元和a[n-1]选出最小元:
C=(3n-3)/2;
12.同时找n个元素中最大与次大元素的好的算法,并说明你给出算法是好的理由。
13.n个元素找中间元素,3、5、7个元素一组时对应的时间复杂度分析
5个元素一组:
设从n个元素中找到指定位置的元素时间为W(n)。
从n个元素中找中间元素的步骤:
1):
5个元素一组对n个元素分组,一共分n/5组,从每一组中的5中找出中间元素要6次比较,时间总共:
n/5*6;
2):
在n/5个组中间元素中再次找中间元素,时间为W(n/5)。
3):
通过1)、2),可粗略的得到元素的分别矩阵,矩阵的左上角的3n/10(3n/5*1/2)个元素均大于中间元素,右下角的3n/10(3n/5*1/2)个元素均小于中间元素。
剩余2n/5(1-3n/10-3n/10)个元素需与中间元素比较,以确定与中间元素的大小关系,时间为2/5n。
4):
2n/5个元素与当前中间元素比较,所用时间为2n/5。
比较结果最坏情况下为2n/5个元素均大于或小于当前中间元素。
5):
在2n/5+3n/10中找特定位置的元素,时间为W(7n/10)。
3个元素一组:
7个元素一组:
14.输入n个元素,输出m个最小的元素,其中(n>
>
m)
(1)将所有n个元素放在数组A中从第n个位置开始的空间里(作为树的叶子),之后n个元素两两一组(A[i],A[i+1])进行比较,使用较小元素的索引作为这两个节点的父亲结点(A[i/2]),之后向上一次建树。
这样可以建立起一棵树T,T的内部结点都是索引值,叶子节点保存实际的数值。
(2)输出当前树T的根节点root指向的值,之后将该值设置成+∞,对树T中root指向的值从叶子节点到根节点经过的路径进行调整,使之满足父结点是两个儿子当中值较小者的索引。
(3)反复执行第2步,直到找够m个最小元素。
15.对于如下输入序列,画出红黑树的生成过程。
1,6,4,8,9,7,2,5,3
插入的结点
插入后的状况
操作步骤
1
黑
……
6
黑红
4
黑红红
s1:
变色(1变红,4变黑);
s2:
反向(改为4指向1,并且4还要指向1);
s3:
移儿子(4的左儿子变成1的右儿子,4的右儿子变成6的左儿子);
s4:
移根(根由1变为4)
8
红黑红红
同层已存在的结点变色(1变黑,4变红,6变黑);
抬根(4被抬高);
变色(4变黑)
9
变色(6变红,8变黑);
反向(改为8指向6);
移儿子(8的左儿子变成6的右儿子);
移根(这一层的根由6变为8)
7
同层已存在的结点变色(6变黑,8变红,9变黑);
抬根(8被抬高)
2
5
红黑红
3
变色(1变红,2变黑);
反向(改为2指向1);
移儿子(2的左儿子变成1的右儿子);
移根(这一层的根由1变为2)
16.红黑树证明:
高度为h的红黑树T的内部黑节点数至少为2^h-1
高度为h的红黑树T的内部节点数至多为4^h-1
任意黑色节点的深度最多是其黑色深度的2倍
设一个黑色节点的深度为h,即它到达根节点经过的边数为h,也就是说经过的节点数(包括根节点且不包括该黑色节点本身)为h。
由于红黑树中不会出现红色节点有红色的子节点,故每一个红色节点一定会连向至少一个黑色节点。
设所经过的红色节点数为x,黑色节点数为y,则x<
=y,故h=x+y<
=y+y=2y,而该黑色节点的黑色深度即为y,说明该黑色节点的深度h<
=2y,即小于其黑色深度的2倍,命题得证。
红黑树应用
给定一个数组,元素长度高达n=10,000,000,
元素大小在32位整数以内,
再给定m=10,000,000个区间[0,r],
和一个整数k,
表示数组下标从0到r的所有元素中,
第k小的数是多少?
(k满足1<
=k<
=r+1)
如果采用暴力解法,即对于每一个区间进行排序,然后直接选取第k小元素。
时间复杂度O(m*n*log(n)),最坏情况下操作次数高达2.3*10^15。
优化:
用红黑树来查找第k小元素。
考虑到红黑树是一颗基本平衡的二叉搜索树,利用二叉搜索树的性质我们可以很容易得到一个集合内的第k小元素是多少。
只需要在每个节点中记录以该节点为根的子树中节点个数即可。
从根节点作为当前节点开始查找第k小的元素,如果左孩子节点数等于k–1个,则当前节点即为所求元素,否则假设左孩子节点数为c个,如果c小于k-1个,则在右子树中查找第(k-1-c)小元素,否则在左子树中查找第k小元素。
如此处理,最终可以以O(logn)的复杂度查找第k小元素
这样做之后,发现如果直接每一个区间建立一个红黑树,复杂度仍为O(m*n*log(n)),考虑系数甚至比以前更差。
我们可以把区间按照右端点r排序,然后往红黑树里一个一个的插入元素,当红黑树里元素正好满足某个区间时求其解,可以将复杂度降低至O(m*log(m)+n*log(n)+m*log(n)),易知求解得顺序正好符号我们区间排序后的顺序。
16.动态数组规划
当需要增大数组时,将当前数组大小乘4,或者将当前数组大小乘2。
评价这两种方法
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 大连理工大学 算法 设计 讲解