最新算法分析与设计习题集答案Word格式.docx
《最新算法分析与设计习题集答案Word格式.docx》由会员分享,可在线阅读,更多相关《最新算法分析与设计习题集答案Word格式.docx(47页珍藏版)》请在冰豆网上搜索。
这部分空间的大小与输入/输出的数据的个数多少、数值无关。
主要包括指令空间(即代码空间)、数据空间(常量、简单变量)等所占的空间。
这部分属于静态空间。
(2)可变空间,这部分空间的主要包括动态分配的空间,以及递归栈所需的空间等。
这部分的空间大小与算法有关。
一个算法所需的存储空间用f(n)表示。
S(n)=O(f(n))
其中n为问题的规模,S(n)表示空间复杂度。
4、什么是最坏时间复杂性?
什么是最好时间复杂性?
答:
最坏情况时间复杂性:
最好情况时间复杂性:
:
I*是DN中使T(N,I*)达到Tmax(N)的合法输入;
P(I)是在算法的应用中出现输入I的概率
5、什么是递归算法?
什么是递归函数?
递归算法(包括直接递归和间接递归子程序)都是通过自己调用自己,将求解问题转化成性质相同的子问题,最终达到求解的的。
递归算法充分地利用了计算机系统内部机能,自动实现调用过程中对相关且必要的信息的保存与恢复,从而省略了求解过程中的许多细节的描述。
【课本】
直接递归子程序在运行完成前调用它们自己。
间接递归子程序在运行过程中调用其它子程序,其他子程序反过来调用这个调用子程序。
递归函数,把直接或间接地调用自身的函数称为递归函数。
函数的构建通常需要一个函数或者一个过程来完成。
网上:
(1)递归算法:
直接或间接地调用自身的算法;
(2)递归函数:
用函数自身给出递归定义的函数。
6、分治法的设计思想是什么?
将整个问题分成若干个小问题后分而治之
给定一个有n个输入的函数,分治策略建议将输入分为k个不同的子集,1<
k≤n,从而产生k个子问题。
当输入规模n取值较大时,可以将这n个输入分成k(1<
k≤n)个不同子集合的情况下,得到k个不同的可独立求解的子问题,求出这些子问题的解之后,再用适当的方法把它们合并成整个问题的解。
这就是分治法。
如果子问题仍然较大,可以再次使用分治策略。
更精确地说,分治策略将输入划分为与原问题同类型的k个子问题。
许多时候,k=2。
7、动态规划基本步骤是什么?
(1)找出最优解的性质,并刻划其结构特征;
(2)递归地定义最优值;
(3)以自底向上的方式计算出最优值;
(4)根据计算最优值时得到的信息,构造最优解。
8、回溯法与分枝限界法之间的相同点是什么?
不同之处在哪些方面?
同:
他们同是在问题的解空间树上搜索问题解的算法;
异:
(1)求解目标:
回溯法的求解目标是找出解空间树中满足约束条件的所有解,而分支限界法的求解目标则是找出满足约束条件的一个解,或是在满足约束条件的解中找出在某种意义下的最优解;
(2)搜索方式的不同:
回溯法以深度优先的方式搜索解空间树,而分支限界法则以广度优先或以最小耗费优先的方式搜索解空间树。
9、分枝限界法的基本思想是什么?
分支限界法常以广度优先或以最小耗费(最大效益)优先的方式搜索问题的解空间树。
10、限界函数的功能是什么?
用限界函数剪去得不到最优解的子树
11、设某一函数定义如下:
编写一个递归函数计算给定x的M(x)的值。
本函数是一个递归函数,其递归出口是:
M(x)=x-10x>
100
递归体是:
M(M(x+11))x≤100
实现本题功能的递归函数如下:
intm(intx)
{inty;
if(x>
100)return(x-10);
else{
y=m(x+11);
return(m(y));
}
procedureM(x)
ifx>
100then
return(x-10)
else
returnM(M(x+11))
endif
endM
12、已知一个顺序表中的元素按元素值非递减有序排列,编写一个函数删除表中多余的值相同的元素。
本题的算法思想是:
由于顺序表中元素已按元素值非递减有序排列,值相同的元素比为相邻的元素,因此依次比较相邻两个元素,若值相等,则删除其中一个,否则继续向后查找,直到最后一个元素。
实现本题功能的函数如下:
voiddel(seqlist*a)
{
inti=0,j;
while(i<
a->
length)
if(a->
data[i]!
=a->
data[i+1])i++;
else
for(j=i;
j<
length;
j++)a->
data[j]=a->
data[j+1];
length--;
proceduredel(A,LINK,n)
//A(1:
n)是元素按元素值非递减有序排列的顺序表,LINK(1:
n)每个数的下一个数所在的下标,等于0时表示后面再没有数了,初始时为2,3,4……n,0
globalintegerA(1:
n),LINK(1:
n)
integeri,j;
i←1;
whileLINK(i)>
0do
j←LINK(i)
whilej<
nandA(i)=A(j)do//查找是否为相同的数
j←LINK(j);
repeat
LINK(i)←j;
//将i的LINK指向j,忽略中间相同的数
i←j;
enddel
13、分别写出求二叉树结点总数及叶子总数的算法。
①计算结点总数
intCountNode(BinTree*root)
intnum1,num2;
if(root==Null)return(0);
elseif(root->
lchild==Null&
&
rooot->
rchild==Null)
return
(1);
{
num1=CountNode(root->
lchild);
num2=CountNode(root->
rchild);
return(num1+num2+1);
}
procedureCOUNTNODE(T)
//T是一棵二元树。
T的每个结点有三个信息段:
LCHILD、DATA、RCHILD
integernum1,num2;
ifT!
=0then
ifLCHILD(T)=0andRCHILD(T)=0then//既没有左孩子,也没有右孩子,则为叶子节点
num1=COUNTNODE(LCHILD(T));
num2=COUNTNODE(RCHILD(T));
//将左右子树的结点数加起来,再加本身,相当时树的后序遍历
endfi
return(0);
endCOUNTNODE
②计算叶子总数
intCountLeafs(BinTree*root)
root->
num1=CountLeafs(root->
num2=CountLeafs(root->
return(num1+num2);
procedureCOUNTLEAFS(T)
num1=COUNTLEAFS(LCHILD(T));
num2=COUNTLEAFS(RCHILD(T));
return(num1+num2);
//T为空时,没有结点
endCOUNTLEAFS
分治术
14、有金币15枚,已知其中有一枚是假的,而且它的重量比真币轻。
要求用一个天平将假的金币找出来,试设计一种算法(方案),使在最坏情况下用天平的次数最少。
procedureSELECKP(p,q)
//A是一个全程数组,分别表示n个硬币的重量,在本题中表示15个硬币;
p和q表示假币所在的一组硬币的起始和终止编号;
最后返回硬币的编号;
在主程序中调用SELECKP(1,15)
ifp=q
then
return(p);
endif;
globalingegerA(p:
q);
integera,b,c,d,m;
a←p;
//第一组数的起始编号
d←q;
//第二组硬币的终止编号
m←0;
//最多余的一个硬币所在的编号
if(ISODD(q-p+1))//如果该组硬币数量为d奇数
thenm←q;
//最后一个数不作比较
d←d-1;
edif
c←(a+d+1)/2;
//第二组硬币的起始编号编号
b←b-1;
//第一组硬币的终止编号
//将该组硬币分为平均分为两组,然后用天平比较两组重量,将轻的一组递归调用本方法
IfWEIGHT(a,b)<
WEIGHT(c,d)
thenreturn(SELECKP(a,b));
elseifWEIGHT(a,b)>
thenreturn(SELECKP(c,d));
elseifm!
=0//若两组硬币重量相等,则剩下一个为假币
return(m);
else//如果两组硬币重量相等,且没有不比较的硬币,即本次检查的硬币总数为偶数,表示没有硬币
print("
没有假币"
);
endSELECKP
15、利用分治策略,在n个不同元素中找出第k个最小元素。
procedureSELECT(A,n,k)
//在数组A
(1),……,A(n)中找出第k小元素s并把它放在位置k,假设1<
=k<
=n。
将剩下的元素按如下方式重新排列,使A(k)=t,有A(m)<
=t,有A(m)<
=t;
对于k<
m<
=n,有A(m)>
=t.A(n+1)=+∞//
integern,k,m,r,j;
m←1r←n+1;
A(n+1)←+∞;
loop//每当进入这一循环时,1<
=m<
=r<
=n+1//
j←r//将剩下的元素的最大下