1、数据结构第六章第六章 树和二叉树 6.33 int Is_Descendant_C(int u,int v)/在孩子存储结构上判断u是否v的子孙,是则返回1,否则返回0if(u=v) return 1;elseif(Lv)if (Is_Descendant(u,Lv) return 1;if(Rv)if (Is_Descendant(u,Rv) return 1; /这是个递归算法return 0;/Is_Descendant_C 6.34 int Is_Descendant_P(int u,int v)/在双亲存储结构上判断u是否v的子孙,是则返回1,否则返回0for(p=u;p!=v&p;
2、p=Tp);if(p=v) return 1;else return 0;/Is_Descendant_P 6.35 这一题根本不需要写什么算法,见书后注释:两个整数的值是相等的. 6.36 int Bitree_Sim(Bitree B1,Bitree B2)/判断两棵树是否相似的递归算法if(!B1&!B2) return 1;else if(B1&B2&Bitree_Sim(B1-lchild,B2-lchild)&Bitree_Sim(B1-rchild,B2-rchild)return 1;else return 0;/Bitree_Sim 6.37 void PreOrder_No
3、nrecursive(Bitree T)/先序遍历二叉树的非递归算法InitStack(S);Push(S,T); /根指针进栈while(!StackEmpty(S)while(Gettop(S,p)&p)visit(p-data);push(S,p-lchild); /向左走到尽头pop(S,p);if(!StackEmpty(S) pop(S,p); push(S,p-rchild); /向右一步/while/PreOrder_Nonrecursive 6.38 typedef struct BTNode* ptr; enum 0,1,2 mark; PMType; /有mark域的结点
4、指针类型 void PostOrder_Stack(BiTree T)/后续遍历二叉树的非递归算法,用栈PMType a;InitStack(S); /S的元素为PMType类型Push (S,T,0); /根结点入栈while(!StackEmpty(S)Pop(S,a);switch(a.mark)case 0:Push(S,a.ptr,1); /修改mark域if(a.ptr-lchild) Push(S,a.ptr-lchild,0); /访问左子树break;case 1:Push(S,a.ptr,2); /修改mark域if(a.ptr-rchild) Push(S,a.ptr-r
5、child,0); /访问右子树break;case 2:visit(a.ptr); /访问结点,返回/while/PostOrder_Stack分析:为了区分两次过栈的不同处理方式,在堆栈中增加一个mark域,mark=0表示刚刚访问此结点,mark=1表示左子树处理结束返回,mark=2表示右子树处理结束返回.每次根据栈顶元素的mark域值决定做何种动作. 6.39 typedef struct int data; EBTNode *lchild; EBTNode *rchild; EBTNode *parent; enum 0,1,2 mark; EBTNode,EBitree; /有m
6、ark域和双亲指针域的二叉树结点类型 void PostOrder_Nonrecursive(EBitree T)/后序遍历二叉树的非递归算法,不用栈p=T;while(p)switch(p-mark)case 0:p-mark=1;if(p-lchild) p=p-lchild; /访问左子树break;case 1:p-mark=2;if(p-rchild) p=p-rchild; /访问右子树break;case 2:visit(p);p-mark=0; /恢复mark值p=p-parent; /返回双亲结点/PostOrder_Nonrecursive分析:本题思路与上一题完全相同,只
7、不过结点的mark值是储存在结点中的,而不是暂存在堆栈中,所以访问完毕后要将mark域恢复为0,以备下一次遍历. 6.40 typedef struct int data; PBTNode *lchild; PBTNode *rchild; PBTNode *parent; PBTNode,PBitree; /有双亲指针域的二叉树结点类型 void Inorder_Nonrecursive(PBitree T)/不设栈非递归遍历有双亲指针的二叉树p=T;while(p-lchild) p=p-lchild; /向左走到尽头while(p)visit(p);if(p-rchild) /寻找中序后
8、继:当有右子树时p=p-rchild;while(p-lchild) p=p-lchild; /后继就是在右子树中向左走到尽头else if(p-parent-lchild=p) p=p-parent; /当自己是双亲的左孩子时后继就是双亲elsep=p-parent;while(p-parent&p-parent-rchild=p) p=p-parent;p=p-parent; /当自己是双亲的右孩子时后继就是向上返回直到遇到自己是在其左子树中的祖先/while/Inorder_Nonrecursive 6.41 int c,k; /这里把k和计数器c作为全局变量处理 void Get_Pr
9、eSeq(Bitree T)/求先序序列为k的结点的值if(T)c+; /每访问一个子树的根都会使前序序号计数器加1if(c=k)printf(Value is %dn,T-data);exit (1);elseGet_PreSeq(T-lchild); /在左子树中查找Get_PreSeq(T-rchild); /在右子树中查找/if/Get_PreSeq main().scanf(%d,&k);c=0; /在主函数中调用前,要给计数器赋初值0Get_PreSeq(T,k);./main 6.42 int LeafCount_BiTree(Bitree T)/求二叉树中叶子结点的数目if(!
10、T) return 0; /空树没有叶子else if(!T-lchild&!T-rchild) return 1; /叶子结点else return Leaf_Count(T-lchild)+Leaf_Count(T-rchild);/左子树的叶子数加上右子树的叶子数/LeafCount_BiTree 6.43 void Bitree_Revolute(Bitree T)/交换所有结点的左右子树T-lchildT-rchild; /交换左右子树if(T-lchild) Bitree_Revolute(T-lchild);if(T-rchild) Bitree_Revolute(T-rchil
11、d); /左右子树再分别交换各自的左右子树/Bitree_Revolute 6.44 int Get_Sub_Depth(Bitree T,int x)/求二叉树中以值为x的结点为根的子树深度if(T-data=x)printf(%dn,Get_Depth(T); /找到了值为x的结点,求其深度exit 1;elseif(T-lchild) Get_Sub_Depth(T-lchild,x);if(T-rchild) Get_Sub_Depth(T-rchild,x); /在左右子树中继续寻找/Get_Sub_Depth int Get_Depth(Bitree T)/求子树深度的递归算法if
12、(!T) return 0;elsem=Get_Depth(T-lchild);n=Get_Depth(T-rchild);return (mn?m:n)+1;/Get_Depth 6.45 void Del_Sub_x(Bitree T,int x)/删除所有以元素x为根的子树if(T-data=x) Del_Sub(T); /删除该子树elseif(T-lchild) Del_Sub_x(T-lchild,x);if(T-rchild) Del_Sub_x(T-rchild,x); /在左右子树中继续查找/else/Del_Sub_x void Del_Sub(Bitree T)/删除子树
13、Tif(T-lchild) Del_Sub(T-lchild);if(T-rchild) Del_Sub(T-rchild);free(T);/Del_Sub 6.46 void Bitree_Copy_Nonrecursive(Bitree T,Bitree &U)/非递归复制二叉树InitStack(S1);InitStack(S2);push(S1,T); /根指针进栈U=(BTNode*)malloc(sizeof(BTNode);U-data=T-data;q=U;push(S2,U);while(!StackEmpty(S)while(Gettop(S1,p)&p)q-lchild
14、=(BTNode*)malloc(sizeof(BTNode);q=q-lchild;q-data=p-data;push(S1,p-lchild);push(S2,q); /向左走到尽头pop(S1,p);pop(S2,q);if(!StackEmpty(S1) pop(S1,p);pop(S2,q); q-rchild=(BTNode*)malloc(sizeof(BTNode); q=q-rchild;q-data=p-data; push(S1,p-rchild); /向右一步 push(S2,q);/while/BiTree_Copy_Nonrecursive分析:本题的算法系从6.
15、37改写而来. 6.47 void LayerOrder(Bitree T)/层序遍历二叉树InitQueue(Q); /建立工作队列EnQueue(Q,T);while(!QueueEmpty(Q)DeQueue(Q,p);visit(p);if(p-lchild) EnQueue(Q,p-lchild);if(p-rchild) EnQueue(Q,p-rchild);/LayerOrder 6.48 int found=FALSE; Bitree* Find_Near_Ancient(Bitree T,Bitree p,Bitree q)/求二叉树T中结点p和q的最近共同祖先Bitree
16、 pathp 100 ,pathq 100 /设立两个辅助数组暂存从根到p,q的路径Findpath(T,p,pathp,0);found=FALSE;Findpath(T,q,pathq,0); /求从根到p,q的路径放在pathp和pathq中for(i=0;pathpi=pathqi&pathpi;i+); /查找两条路径上最后一个相同结点return pathp-i;/Find_Near_Ancient void Findpath(Bitree T,Bitree p,Bitree path ,int i)/求从T到p路径的递归算法if(T=p)found=TRUE;return; /找
17、到pathi=T; /当前结点存入路径if(T-lchild) Findpath(T-lchild,p,path,i+1); /在左子树中继续寻找if(T-rchild&!found) Findpath(T-rchild,p,path,i+1); /在右子树中继续寻找if(!found) pathi=NULL; /回溯/Findpath 6.49 int IsFull_Bitree(Bitree T)/判断二叉树是否完全二叉树,是则返回1,否则返回0InitQueue(Q);flag=0;EnQueue(Q,T); /建立工作队列while(!QueueEmpty(Q)DeQueue(Q,p)
18、;if(!p) flag=1;else if(flag) return 0;elseEnQueue(Q,p-lchild);EnQueue(Q,p-rchild); /不管孩子是否为空,都入队列/whilereturn 1;/IsFull_Bitree分析:该问题可以通过层序遍历的方法来解决.与6.47相比,作了一个修改,不管当前结点是否有左右孩子,都入队列.这样当树为完全二叉树时,遍历时得到是一个连续的不包含空指针的序列.反之,则序列中会含有空指针. 6.50 Status CreateBitree_Triplet(Bitree &T)/输入三元组建立二叉树if(getchar()!=) r
19、eturn ERROR;T=(BTNode*)malloc(sizeof(BTNode);p=T;p-data=getchar();getchar(); /滤去多余字符InitQueue(Q);EnQueue(Q,T);while(parent=getchar()!=&(child=getchar()&(side=getchar()while(QueueHead(Q)!=parent&!QueueEmpty(Q) DeQueue(Q,e);if(QueueEmpty(Q) return ERROR; /未按层序输入p=QueueHead(Q);q=(BTNode*)malloc(sizeof(
20、BTNode);if(side=L) p-lchild=q;else if(side=R) p-rchild=q;else return ERROR; /格式不正确q-data=child;EnQueue(Q,q);return OK;/CreateBitree_Triplet 6.51 Status Print_Expression(Bitree T)/按标准形式输出以二叉树存储的表达式if(T-data是字母) printf(%c,T-data);else if(T-data是操作符)if(!T-lchild|!T-rchild) return ERROR; /格式错误if(T-lchil
21、d-data是操作符&T-lchild-data优先级低于T-data)printf();if(!Print_Expression(T-lchild) return ERROR;printf(); /注意在什么情况下要加括号else if(!Print_Expression(T-lchild) return ERROR;if(T-rchild-data是操作符&T-rchild-data优先级低于T-data)printf();if(!Print_Expression(T-rchild) return ERROR;printf();else if(!Print_Expression(T-rch
22、ild) return ERROR;else return ERROR; /非法字符return OK;/Print_Expression 6.52 typedef struct BTNode node; int layer; BTNRecord; /包含结点所在层次的记录类型 int FanMao(Bitree T)/求一棵二叉树的繁茂度int countd; /count数组存放每一层的结点数InitQueue(Q); /Q的元素为BTNRecord类型EnQueue(Q,T,0);while(!QueueEmpty(Q)DeQueue(Q,r);countr.layer+;if(r.no
23、de-lchild) EnQueue(Q,r.node-lchild,r.layer+1);if(r.node-rchild) EnQueue(Q,r.node-rchild,r.layer+1); /利用层序遍历来统计各层的结点数h=r.layer; /最后一个队列元素所在层就是树的高度for(maxn=count0,i=1;counti;i+)if(countimaxn) maxn=counti; /求层最大结点数return h*maxn;/FanMao分析:如果不允许使用辅助数组,就必须在遍历的同时求出层最大结点数,形式上会复杂一些,你能写出来吗? 6.53 int maxh; Sta
24、tus Printpath_MaxdepthS1(Bitree T)/求深度等于树高度减一的最靠左的结点Bitree pathd;maxh=Get_Depth(T); /Get_Depth函数见6.44if(maxhdata);exit; /打印输出路径elseif(T-lchild) Find_h(T-lchild,h+1);if(T-rchild) Find_h(T-rchild,h+1);pathh=NULL; /回溯/Find_h 6.54 Status CreateBitree_SqList(Bitree &T,SqList sa)/根据顺序存储结构建立二叉链表Bitree ptrsa.last+1; /该数组储存与sa中各结点对应的树指针if(!sa.last
copyright@ 2008-2022 冰豆网网站版权所有
经营许可证编号:鄂ICP备2022015515号-1