设前序序列为:
a1,a2,…,am,中序序列为:
b1,b2,…,bm。
因为前序序列由前序遍历得到,则a1为根结点元素;又中序序列由中序遍历得到,则在中序序列中必能找到和a1相同的元素并设为bj(1≤j≤m),由此可得{b1,…,bj-1}为左子树的中序序列,{bj+1,…,bm}为右子树的中序序列。
(1)若j=1即b1为根,此时二叉树的左子树为空,{a2,…,am}即为右子树的前序序列,{b2,…,bm}即为右子树的中序序列,右子树的结点数为m-1,由此,这两个序列唯一确定了右子树,也唯一确定了二叉树。
(2)若j=m即bm为根,此时二叉树的右子树为空,{a2,…,am}即为左子树的前序序列,{b2,…,bm}即为左子树的中序序列,同
(1),这两个序列唯一确定了左子树,也唯一确定了二叉树。
(3)2≤j≤m-1,则子序列{a2,…,aj}和{b1,…,bj-1}分别为左子树的前序序列和中序序列,这两个序列唯一确定了左子树;子序列{aj+1,…,am}和{bj+1,…,bm}分别为右子树的前序序列和中序序列,这两个序列唯一确定了右子树;
由此,证明了知道一棵二叉树的前序序列和中序序列,就能唯一地确定一棵二叉树。
5.
6.
7.
8.
F
五.算法设计题
=p;
p=p->lchild;
}
if(top!
=-1)returnstack[top].T;
elsereturnNULL;
}
6.
BiThrNode*PreOrder_Next(BiThrNode*p){
n");v=0;}
else{
p=(q->front)->next;
(q->front)->next=p->next;
if(p->next==NULL)q->rear=q->front;
v=p->T;
free(p);
}
returnv;
}
voidvisite(LINKQUEUE*q,BiTreep)
{if(p!
=NULL)
{printf("%c",p->data);
enlinkqueue(q,p);
}
}
voidLevel_Traverse(BiTreeT)/*按层次遍历二叉树*/
{LINKQUEUEQue,*Q;
BiTreep;
Q=&Que;
initlinkqueue(Q);
if(T!
=NULL)
{visite(Q,T);
while(!
emptylinkqueue(Q))
{p=dellinkqueue(Q);
visite(Q,p->lchild);
visite(Q,p->rchild);
}
printf("ThepointerwhichpointsatthelastNodeis%x\n",p);
/*给出离根结点最远的一个结点(即最后一个出队的结点)的指针*/
}
}
8.
intNode(BiTreeT)
{/*求以孩子兄弟链表存储的树或森林T中的结点数,并通过函数值返回*/
intcount;
BiTreeT1;
if(T==NULL)return0;/*bt为空时,结点数为0*/
elseif(T->firstchild==NULL)return1;
else{
count=0;T1=T->firstchild;
while(T1)
{count=cout+Node(T1);T1=T1->nextsibling?
;}
returncount?
;
}
}
9.
intHigh(BiTreeT)
{/*求以孩子兄弟链表存储的树或森林T的高度,并通过函数值返回*/
inth1,h2;
BiTreeT1;
if(T==NULL)return0;/*bt为空时,结点数为0*/
else{
h1=High(T->firstchild)+1;
h2=High(T->nextsibling);
returnh1>h2?
h1:
h2;
}
}
10.
charPred,Midd;.
Build_Sub(1,n,1,n);.
}
分析:
本算法利用了这样一个性质,即一棵子树在前序和中序序列中所占的位置总是连续的.因此,就可以用起始下标和终止下标来确定一棵子树.Pre_Start,Pre_End,Mid_Start和Mid_End分别指示子树在前序子序列里的起始下标,终止下标,和在中序子序列里的起始和终止下标.
第7章图
一、选择题
1.B2.B3.B和C4.D和E5.C6.D7.A8.A9.D10.B
二、填空题
1.[1]n(n-1)[2]n(n-2)/2[3]n-1
2.[1]ABCDFE[2]ABCEFD
3.[1]按深度[2]按广度
4.极大
5.图本身
6.主对角线
7.[1]i[2]j
8.[1]n-1[2]大于n-1[3]小于n-1
9.20
10.[1]n+2e[2]2e[3]n
11.[1]n+e[2]e[3]n
12.无环
三、判断题
1.×2.√3.√4.×5.×6.×7.×8.×
四、(略)
五、(略)
第8章查找
一、选择题
1、C2、B3、A4、C5、C6、D7、B8、B9、B10、D
11、C12、C13、D14、D15、D16、C17、A18、B19、D20、B
二、判断题
1.【答案】错误
【分析】顺序查找并没有假设数有序或者无序,因此有序或无序对平均查找长度没有影响。
2.【答案】错误
3.【答案】正确
4.【答案】错误
【分析】链表表示的有序表不能用折半查找法查找。
5.【答案】错误
6.【答案】错误
【分析】最优二叉树是静态树表,AVL是动态树表,二者范围不同。
7.【答案】正确
8.【答案】正确
9.【答案】正确
10.【答案】正确
11.【答案】错误
【分析】除非被删除的结点是叶子结点,否则删除后再插入同一结点得到的二叉排序树与原来的二叉排序树不同。
12.【答案】错误
13.【答案】错误
14.【答案】错误
15.【答案】正确
16.【答案】正确
17.【答案】错误
【分析】а越小,只能说发生冲突的可能性越小,但依然有可能发生冲突。
18.【答案】正确
19.【答案】正确
20.【答案】正确
三、填空题
1.【分析】最优二叉树是对叶子结点带权平均查找路径长度最小的树,最优查找树是对所有结点带权查找路径长度最小的树,构造这两种树均需要知道关键字的查找概率。
【解答】①叶子结点数②结点数③需要n个关键字的查找概率表
2.【分析】折半查找法在查找成功与不成功时进行比较的关键字个数最多不超过树的深度,而具有n个结点的判定树的深度为?
log2n」+1,所以,最大比较次数为?
log2n」+1。
【答案】?
log2n」+1
3.【分析】平均检索长度ASLss=(s+n/s)/2+1,所以当S=
时,ASLss取得最小值
+1。
【解答】①16②17③21
4.【分析】第4层是叶子结点,每个结点两个关键字,2×1+2×31+2×32=26。
【答案】26
四、简答题
1.【解答】判定树如下所示:
等概率查找时成功的平均查找长度为ASLsucc=
(1×1+2×2+3×4+4×3)=
2.【解答】
(1)按关键字的顺序构造的二叉排序树:
(2)根据构造的二叉排序树,求查找成功时的平均查找长度:
ASLSUCC=(1*1+2*2+3*3+4*3+5*2+6*1)/12=
(3)若对表中元素先进行排序构成有序表再构造二叉排序树,则构造的二叉排序树是一棵单支树,在等概率的情况下查找成功的平均查找长度则为:
ASLSUCC=(1+2+…+12)/12=
这种情况就退化成为顺序查找。
3.【解答】
4.【解答】
5.【解答】令Fk表示含有最少结点的深度为k的平衡二叉树的结点数目。
那么,可知道F1=1,F2=2,.....Fn=Fn-2+Fn-1+1.
含有12个结点的平衡二叉树的最大深度为5.例如:
6.【解答】4个、7个。
7.【解答】
8.【分析】主要考察用线性探测再散列法和链地址法构造哈希表。
哈希表的装填因子定义为:
α=表中添入的记录数/哈希表的长度
【解答】
①使用线性探测再散列法来构造哈希表见下表:
地址
012345678910
数据
331131234382722
hashf1
(1)=1hashf1(13)=2
hashf1(12)=1hashf2(12)=(1+1)%11=2hashf3(12)=(1+2)%11=3
hashf1(34)=3hashf2(34)=(3+1)%11=4
hashf1(38)=5hashf1(33)=0
hashf1(27)=5hashf2(27)=(5+1)%11=6
hashf1(22)=0hashf2(22)=(0+1)%11=1hashf3(22)=2hashf4(22)=3
hashf5(22)=4hashf6(22)=5hashf7(22)=6hashf8(22)=7
装填因子?
=8/11
查找成功所需的平均查找次数:
(1+1+3+2+1+1+2+8)/8=19/8
②使用链地址法来构造哈希表如下图所示:
查找成功所需的平均查找次数:
(1*3+2*3+3*1)/8=3/2
9.【解答】
(1)
0
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
Apr
Aug
Dec
Feb
Jan
Mar
May
June
July
Sep
Oct
Nov
平均查找长度为:
31/12
(2)
0
1
^
2
3
4
^
5
6
7
8
^
9
10
^
11
^
12
^
13
^
14
^
15
^
16
^
平均查找长度为:
3/2
五、算法设计题
1.【分析】算法思想:
先遍历右子树后遍历左子树。
【解答】算法如下:
Inorder(BiSTreebt,datatypeX)
{if(bt)
{Inorder(bt->rchild,X);
if(bt->data>=X)printf(“%c”,bt->data);
Inorder(bt->lchild,X);
}
}
2.【分析】在合并过程中,并不释放或新建任何结点,而是采取修改指针的方式来完成合并,这样,就必须按照后序序列把一棵树中元素逐个连接到另一棵树上,否则将会导致树的结构的混乱。
【解答】算法如下:
voidBiTMerge(BiSTree*T,BiSTree*S)/*把二叉排序树合并到T中*/
{if(S->lchild)BiTMerge(T,S->lchild);
if(S->rchild)BiTMerge(T,S->rchild)/*合并子树*/
Insert_Node(T,S);
}
voidInsert(BiSTree*T,BiSTNode*S)/*把树结点S插入到T的合适位置*/
{if(S->data>T->data)
{if(!
T->rchild)T->rchild=S;
elseInsert(T->rchild,S);
}
elseif(S->datadata)
{if(!
T->lchild)T->lchild=S;
elseInsert(T->lchild,S);
}
S->lchild=NULL;/*插入的新结点必须和原来的左右子树断绝关系*/
S->rchild=NULL;/*否则会导致树结构的混乱*/
}
3.【分析】算法思想;以x为分界点遍历原二叉树并构造两棵新的二叉排序树。
【解答】算法如下:
voidBiTSplit(BiSTree*T,BiSTree*A,BiSTree*B,intx)
/*把二叉排序树T分裂为两棵二叉排序树A和B,其中A的元素全部小于等于x,B的元素全部大于x*/
{if(T->lchild)BiTSplit(T->lchild,A,B,x);
if(T->rchild)BiTSplit(T->rchild,A,B,x);/*分裂左右子树*/
if(T->data<=x)Insert(A,T);
elseInsert(B,T);/*将元素结点插入到T的合适位置上*/
}