1. 程式人生 > >根據先序和中序(中序和後序)確定二叉樹

根據先序和中序(中序和後序)確定二叉樹

實在是恨自己智商欠費,一個二叉樹搞了好長時間才弄清!!!
怎樣通過先序和中序確定二叉樹?
我的演算法設計思路參考學習網上的,但程式碼是自己實現的,其實還是在建立二叉樹的基礎上新增一些條件。我們剛開始根據先序序列中第一個資料,在中序序列中找與該結點資料相等的與元素,將中序序列中該元素所在下標返回。建立節點,將先序序列的第一個有效元素存起來。將中序序列中與前序序列當前第一個元素相等的元素所在位置置為’\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;
}