根据前序、中序遍历重构二叉树

来源:互联网 发布:淘宝详情页设计价格 编辑:程序博客网 时间:2024/04/30 16:33

 本文来源

 

【前言】

这个选题源自课上的一个习题,题目提供了二叉树的前序遍历和中序遍历,要求出整个二叉树。刚一做这道题时,还有些迷惑。但是,既然答案是确定的,就一定存在着算法,来求出这个二叉树。经过一些摸索,最终确定了求解算法。

【分析】

二叉树的遍历一共有四种方法,分别是前序遍历、中序遍历、后续遍历和层序遍历。各种方法各有特点,但是中序遍历的特点最好利用。

中序遍历是先遍历左子树,然后依次遍历根节点、右子树。形成的序列,某个节点的左子树节点全部分布于它的左侧,右子树节点全部分布在它的右侧。这样,就可以通过比对子节点和根节点的相对位置,就可以确定这个节点是左孩子还是右孩子了。

而前序遍历是从上向下、从左往右依次进行的,不会在遍历了根和孩子后,又遍历它们中间的节点。这就是说,我们不用考虑插入节点的问题了。

我的想法是,依次扫描前序遍历的序列,第一个是根节点,直接创建。之后的元素要利用中序遍历的结果,与已生成的节点依次比对,来确定该节点是位于左子树还是右子树。重复这个过程,直到找到最终的位置后,续接在这个位置上,成为一个叶子。当然,这个过程是一个递归的过程了。当前序遍历扫描结束时,二叉树就生成完毕了,问题解决。

【算法实现】

程序用两个字符数组来保存前序遍历和中序遍历的结果,将这个字符数组作为参数在模块间传递,以供各模块使用,同时也降低了个模块间的耦合度。设计一个函数来生成二叉树,还有一个函数建立新节点,这个函数要自身递归,还要设计一个函数来扫描字符串,确定应该位于左还是右子树。

值得注意的是,建立新节点的函数要为节点分配内存,所以要采用传址传递,本质是传入指针的指针。另外,还应考虑二叉树的输出问题,这里采用文本模式输出。这里仅仅是一个示例,所以节点数据设计成字符型,以便于理解,而且程序也不对输入的合法性和可行性进行检测。

【源代码】

#include <stdio.h>#include <conio.h>#include <alloc.h>#include <string.h> #define MAXCOUNT 32#define LEFT  0#define RIGHT 1 typedef char Elemtype; typedef struct BtreeNode{   Elemtype Data;   struct BtreeNode *LChild,*RChild;}BTREENODE,*BTREENODEPTR,*BTREE; typedef struct Pos{   int x,y;}BTREENODEPOS; BTREENODEPOS BtnPos[MAXCOUNT]; void InitBtreeNodePos(void){   int i;   for(i=0;i<16;i++)   {       BtnPos[16+i].x=25+i*2;       BtnPos[16+i].y=16;   }   for(i=15;i>=1;i--)   {       BtnPos[i].x=(BtnPos[2*i].x+BtnPos[2*i+1].x)/2;       BtnPos[i].y=BtnPos[2*i].y-2;   }} void DestroyBtree(BTREE Root){   if(Root==NULL)return;   DestroyBtree(Root->LChild);   DestroyBtree(Root->RChild);   Root->LChild=NULL;   Root->RChild=NULL;   free(Root);} void ShowBtree(BTREE Root,int Index){   int i,j;    if(Root==NULL)return;   i=Index*2;   j=Index*2+1;   gotoxy(BtnPos[Index].x,BtnPos[Index].y);   printf("%c",Root->Data);   if(i<MAXCOUNT) ShowBtree(Root->LChild,i);   if(j<MAXCOUNT) ShowBtree(Root->RChild,j);} int GetLR(char *PreOrder,char *InOrder,int i,int Data){   int j=0,k=0;    while(PreOrder[i]!=InOrder[j]) j++;   while(Data!=InOrder[k]) k++;   if(j<k) return LEFT; else return RIGHT;} void AddBtreeNode(BTREE *Root,char *PreOrder,char *InOrder,int i){   if(*Root==NULL)   {       (*Root)=(BTREENODE*)malloc(sizeof(BTREENODE));       (*Root)->Data=PreOrder[i];       (*Root)->LChild=NULL;       (*Root)->RChild=NULL;   }   else   {       if(GetLR(PreOrder,InOrder,i,(*Root)->Data)==LEFT)          AddBtreeNode(&(*Root)->LChild,PreOrder,InOrder,i);       else          AddBtreeNode(&(*Root)->RChild,PreOrder,InOrder,i);   }} BTREE CreatBtreeByOrder(void){   char PreOrder[32],InOrder[32];   BTREE Root=NULL;   int i;    printf("Input PreOrder:");   gets(PreOrder);   printf("Input InOrder :");   gets(InOrder);   for(i=0;PreOrder[i]!=0;i++)       AddBtreeNode(&Root,PreOrder,InOrder,i);   return Root;} void main(){   BTREE Root;    clrscr();   InitBtreeNodePos();   Root=CreatBtreeByOrder();   ShowBtree(Root,1);   DestroyBtree(Root);}


 

原创粉丝点击