二叉树的遍历 分类: 数据结构 2015-07-20 22:34 4人阅读 评论(0) 收藏
#include<stdio.h> #include<string.h> #include<windows.h> #include<stdlib.h> #include<stack> #include<iostream> #define max 500 using namespace std; typedef struct node { char data; struct node *left ,*right; }binode,*bitree;//树结构 typedef struct { bitree num[max]; int top; }sqstack;//栈结构 typedef struct kk { bitree t; struct kk *next; }sqqueue;// typedef struct { sqqueue *front,*rear; }queue;//层次遍历时用到的队列结构 typedef struct post_y { binode *prt; int flag; }post_type; typedef struct LP { post_type num[max]; int top1; }Sqstack; int initqueue(queue *Q) { sqqueue *p; p=(sqqueue*)malloc(sizeof(sqqueue)); Q->front=p; Q->rear=p; (Q->front)->next=NULL; return 0; }//初始化队列 int queueempty(queue *Q) { if(Q->rear==Q->front) { return 1; } else return 0; }//队列的判空运算 int queuepush(queue *Q,bitree T) { sqqueue *p; p=(sqqueue*)malloc(sizeof(sqqueue)); p->t=T; p->next=NULL; (Q->rear)->next=p; Q->rear=p; return 0; }//元素入队 bitree GET_top(queue *Q) { sqqueue *p; p=(sqqueue*)malloc(sizeof(sqqueue)); bitree q; q=(bitree)malloc(sizeof(bitree)); q->data='1'; q->left=NULL; q->right=NULL; if(queueempty(Q)) { return q; } else { p=(Q->front)->next; return p->t; } }//获取队首元素 int queuepop(queue *Q) { if(queueempty(Q)) { return -1; } else { sqqueue *p; p=(Q->front)->next; (Q->front)->next=p->next; if(p->next==NULL) Q->rear=Q->front; free(p); return 0; } }//元素出队 void creattree(bitree &T) { char s; scanf("%c",&s); if(s=='#') { T=NULL; } else { T=(bitree)malloc(sizeof(binode)); T->data=s; creattree(T->left); creattree(T->right); } }//建树 void visit(bitree T)访问跟操作 { if(T!=NULL) { printf("%c ",T->data); } } void firstvisit(bitree T)//递归实现先序遍历 { if(NULL!=T) { visit(T); firstvisit(T->left); firstvisit(T->right); } }//递归实现先序遍历 void midvisit(bitree T)//递归实现中序遍历 { if(T!=NULL) { midvisit(T->left); visit(T); midvisit(T->right); } }//递归实现中序遍历 void lastvisit(bitree T)//递归实现后序遍历 { if(T!=NULL) { lastvisit(T->left); lastvisit(T->right); visit(T); } }//递归实现后序遍历 void post_visit(bitree T) { Sqstack S; bitree p=NULL; post_type elem; S.top1=-1; p=T; while(NULL!=p||S.top1>-1) { while(NULL!=p) { elem.prt=p; elem.flag=1; S.num[++S.top1]=elem; p=p->left; } elem=S.num[S.top1--]; if(1==elem.flag) { elem.flag=2; S.num[++S.top1]=elem; p=elem.prt->right; } else if(elem.flag==2) { p=elem.prt; printf("%c ",p->data); p=NULL; } } }//非递归实现后序遍历 void previsit(bitree T) { binode *p; p=NULL; sqstack S; S.top=-1; if(NULL!=T) { S.num[++S.top]=T; while(S.top>-1) { p=S.num[S.top--]; printf("%c ",p->data); if(NULL!=p->right) { S.num[++S.top]=p->right; } if(NULL!=p->left) { S.num[++S.top]=p->left; } } } } void inorder(bitree T) { sqstack S; S.top=-1; binode *p=T; while(p||S.top>-1) { while(NULL!=p) { S.num[++S.top]=p; p=p->left; } p=S.num[S.top--]; printf("%c ",p->data); p=p->right; } } void levelvisit(bitree T) { queue *Q; bitree p=T; initqueue(Q); queuepush(Q,T); while(!queueempty(Q)) { p=GET_top(Q); queuepop(Q); printf("%c ",p->data); if(p->left!=NULL) queuepush(Q,p->left); if(p->right!=NULL) queuepush(Q,p->right); } }//层次遍历 void menu() { printf("\t\t选择遍历方式\n"); printf("\t\t1:先序遍历\n"); printf("\t\t2:中序遍历\n"); printf("\t\t3:后序遍历\n"); printf("\t\t4:层次遍历\n"); } int main() { int n; printf("\t\t\t手动输入测试数据\n"); printf("输入节点,其中#表示空子树\n"); bitree T; creattree(T); menu(); while(scanf("%d",&n)!=EOF) { switch(n) { case 1: system("cls"); printf("非递归先序遍历得到的序列\n"); previsit(T); printf("\n"); printf("递归先序遍历得到的序列\n"); firstvisit(T) ; printf("\n"); Sleep(10000); system("cls"); menu(); break; case 2: system("cls"); printf("非递归中序遍历得到的结果\n"); inorder(T); printf("\n"); printf("递归中序遍历得到的序列\n"); midvisit(T); printf("\n"); Sleep(100000); system("cls"); menu(); break; case 3: system("cls"); printf("递归后序遍历得到的序列\n"); lastvisit(T); printf("\n"); printf("非递归后序遍历的到的序列\n"); post_visit(T); printf("\n"); Sleep(10000); system("cls"); menu(); break; case 4: system("cls"); printf("层次遍历得到的序列\n"); levelvisit(T); printf("\n"); Sleep(10000); system("cls"); menu(); break; } } return 0; } 本次测试使用的数据 ABC##DE#G##F### 树的形态 根据先序遍历和中序遍历的结果得到后序遍历结果==
我们知道先序遍历的序列是根+左子树的先序遍历的结果+右子树先序遍历的结果,而中序遍历的结果=左子树的中序遍历结果+根+右子树的中序遍历结果。这样我们就可以根据先序遍历和中序遍历的结果还原这颗二叉树
例如一个二叉树的的先序遍历是ABDECF
后序遍历的结果是DBEAFC
根据遍历的特点我们可知A是整课二叉树的根,那么DBE则是左子树,FC是右子树,然后根据子树的先序遍历和中序遍历的长度相同,左子树的先BDE,左子树的中是DBE,我们又可知B是子树的根....一直这样分下去,直至只有一个节点。。。
#include<stdio.h> #include<string.h> #include<iostream> #include<algorithm> using namespace std; void previs(char *pre , char *in,int len) { if(len<1) return; int i=0; while(in[i]!=pre[0]) i++; previs(pre+1,in,i);//递归求解左子树 previs(pre+1+i,in+1+i,len-i-1);//递归求解右子树 cout<<*(pre); } int main() { string s,ch; cin>>s>>ch; int len=s.size(); previs(s.c_str(),ch.c_str(),len); printf("\n"); return 0; }
版权声明:本文为博主原创文章,未经博主允许不得转载。