根據先序和中序(中序和後序)確定二叉樹
阿新 • • 發佈:2018-11-17
實在是恨自己智商欠費,一個二叉樹搞了好長時間才弄清!!!
怎樣通過先序和中序確定二叉樹?
我的演算法設計思路參考學習網上的,但程式碼是自己實現的,其實還是在建立二叉樹的基礎上新增一些條件。我們剛開始根據先序序列中第一個資料,在中序序列中找與該結點資料相等的與元素,將中序序列中該元素所在下標返回。建立節點,將先序序列的第一個有效元素存起來
。將中序序列中與前序序列當前第一個元素相等的元素所在位置置為’\0’,並將前序序列中的該元素所在位置值置為’\0’,先序序列的首個有效元素也同時應改為下一個元素(即此時遍歷下標應後移)。這是建立二叉樹之前所做的工作。
建立二叉樹還是用遞迴,根據以上返回的下標將中序序列分為兩部分,判斷左邊為空,就將建立節點的左孩子置為空,右邊同理。
若不為空,前半部分為左子樹,後半部分為右子樹。
將前序序列和中序序列前半部分,以及建立的結點的左孩子指標傳進去。遞迴呼叫函式。
將前序序列和中序序列後半部分,以及建立的結點的右孩子指標傳進去。遞迴呼叫函式。
以上所述為火星人理解思路,看不懂不怪你們,怪我,表達上確實欠缺邏輯性,下面我們看程式碼就行~~~
#include<stdlib.h> #include<iostream> #include<string.h> using namespace std; typedef struct node{ char ch ; struct node * l,*r ; }node_t,*node_l; void create_tree(node_l * root,char prelist[],char midlist[]); int findIndex(char prelist,char* midlist); void print(node_l root); int main(){ node_l root ; char prelist[100]; char midlist[100]; bzero(prelist,sizeof(prelist)); bzero(midlist,sizeof(midlist)); cin>>prelist; cin>>midlist; create_tree(&root,prelist,midlist); print(root); } void print(node_l root){ if(root){ print(root->l); print(root->r); cout<<root->ch<<""; } } //該函式時恢復二叉樹的,root為根指,prelist為先序序列,midlist為中序序列 //三者在恢復二叉樹的過程中時變化的 void create_tree(node_l* root,char prelist[],char midlist[]){ //定義靜態變數,因為每次前序每一個元素,就銷燬一個元素, //下標也作相應的移動。 static int index = 0; int mid_index ; //傳入前序序列的首元素,在中序列中搜索 ,記錄元素在中序序列中所處的下標 mid_index = findIndex(prelist[index],midlist); *root = (node_l)malloc(sizeof(node_t)); //將節點資料存在根結點中 (*root)->ch = prelist[index]; 將先序已遍歷的資料全置為‘\0’ prelist[index++]='\0' ; //將中序的那個資料所處位置置為'\0' midlist[mid_index]='\0'; //判斷那個位置之前是否為空,若非空,說明當前節點有左子樹,繼續遞迴建立左子樹 if(midlist[mid_index-1]!='\0'){ create_tree(&((*root)->l),prelist,midlist); } //否則的話就將當前節點的左孩子置為空 else{ (*root)->l = NULL ; } //若當前節點有右孩子,遞迴建立 if(midlist[mid_index+1]!='\0'){ create_tree(&((*root)->r),prelist,&midlist[mid_index+1]); } else{ (*root)->r = NULL ; } } //根據傳進來的中序首元素節點,在中序序列中找該結點下標。 int findIndex(char pre,char * mid){ int i ; for(i = 0; *(mid+i)!= '\0' ;i++){ if(pre == *(mid+i)){ return i ; } } return 0; }
根據後序和中序建立二叉樹時同樣的道理,自己在這個基礎上嘗試找一些規律,就可以自己恢復了。
後序和中序
#include<stdlib.h> #include<iostream> #include<string.h> using namespace std; typedef struct node{ char ch ; struct node * l,*r ; }node_t,*node_l; void create_tree(node_l * root,char lastlist[],char midlist[]); int findIndex(char last,char* midlist); void print(node_l root); int main(){ node_l root ; char lastlist[100]; char midlist[100]; bzero(lastlist,sizeof(lastlist)); bzero(midlist,sizeof(midlist)); cin>>midlist; cin>>lastlist; create_tree(&root,lastlist,midlist); print(root); } void print(node_l root){ if(root){ cout<<root->ch<<""; print(root->l); print(root->r); } } void create_tree(node_l* root,char lastlist[],char midlist[]){ static int index = strlen(lastlist)-1; int mid_index ; mid_index = findIndex(lastlist[index],midlist); *root = (node_l)malloc(sizeof(node_t)); (*root)->ch = lastlist[index]; lastlist[index--]='\0' ; if(index==-1)return ; midlist[mid_index]='\0'; if(midlist[mid_index+1]!='\0'){ create_tree(&((*root)->r),lastlist,&midlist[mid_index+1]); } else{ (*root)->r = NULL ; } if(midlist[mid_index-1]!='\0'){ create_tree(&((*root)->l),lastlist,midlist); } else{ (*root)->l = NULL ; } } int findIndex(char last,char * mid){ int i ; for(i = 0; *(mid+i)!= '\0' ;i++){ if(last == *(mid+i)){ return i ; } } return 0; }