尋找二叉樹中每個結點的根結點(遞歸算法)

筆者查閱了網上關於二叉樹尋找根結點的算法,衆說紛紜,有:在節點結構體中加一條指向父節點的指針;非遞歸遍歷樹的方式尋找父節點;直接利用樹的遞歸遍歷,打印輸出父節點……
筆者認爲添加父節點指針的方法,不能很好地體現樹的邏輯結構。樹的結構體(特指二叉樹的存儲結構)已經很成熟而且近乎約定俗成了,再重新添加一個指針,很多關於二叉樹的基本操作都要重新變化,實在繁瑣。所以本文直接利用樹的遞歸遍歷方式尋找樹的根結點,因爲樹的定義中本就體現了遞歸的特點,所以大多數關於樹的操作,遞歸的方法都可有效實現,而且代碼可讀性強。此外,對於非遞歸方式的解法,本文不再贅述,請讀者自便。
*另:本文只提供一種思路,並不是萬能模板,具體問題還需結合實際情況決定!


【問題描述】構造一棵二叉排序樹(也叫二叉查找樹),可以是一棵空樹。
二叉排序樹定義:
1.若左子樹非空,則左子樹上所有關鍵字值均不大於根結點的關鍵字值;
2.若右子樹非空,則右子樹上所有關鍵字值均不小於根結點的關鍵字值;
3.左、右子樹本身也是一棵二叉排序樹。
現在給你N個關鍵字值各不相同的結點,要求你按順序插入一個初始爲空樹的二叉排序樹中,每次插入成功後,求相應的父節點的關鍵字值。如果沒有父親節點,則輸出-1。
input:
第一行,一個數字N(N<=100),表示待插入的結點數。
第二行,N個互不相同的正整數,表示要順序插入結點的關鍵字值,這些值不超過10^8(即控制在int型數據類型所能表示的範圍內)。
output:
輸出共N行,每次插入節點後,該節點對應的父親節點的關鍵字值。(根結點的父節點默認爲-1)


代碼中採用數組二叉樹的方式存儲樹,有兩點好處:loc值可知結點總數,利於結點遍歷步數的控制;輸入值保存在對應數組,易操作。
指針二叉樹的存儲方法,還望讀者指教。


#include <stdio.h> 

struct Node{
    int data;
    Node* lchild;
    Node* rchild;
}Tree[101]; // 數組二叉樹  
int loc; // loc表示當前節點的個數 
Node* creat(){ // 申請一個樹結點 
    Tree[loc].lchild=Tree[loc].rchild=NULL;
    return &Tree[loc++]; // 返回指向新結點的指針 
} 

/*在一棵二叉樹中,依次插入結點,構造二叉排序樹*/
Node* Insert(Node *T,int x){ 
    if(T==NULL){ 
        T=creat(); 
        T->data=x;
        return T; 
    } 
    else if(x < T->data){
        T->lchild=Insert(T->lchild,x);
    }   
    else if(x > T->data){
        T->rchild=Insert(T->rchild,x);
    }
    return T;
}


/*遍歷一棵樹找到各結點的父節點--先序遍歷模型,注意遍歷孩子節點的條件:孩子非空*/ 
void findParent(Node *T,int x){
    if(!T) return; 
    if(T->lchild!=NULL && T->lchild->data==x) // 左孩子非空纔可遍歷,否則遞歸邊界出錯 
        printf("%d的父節點是:%d\n",x,T->data);
    if(T->rchild!=NULL && T->rchild->data==x)   
        printf("%d的父節點是:%d\n",x,T->data);

    if(T->lchild)   
        findParent(T->lchild,x);
    if(T->rchild)
        findParent(T->rchild,x);
    return; 
}

int main(){
    int n;
    while(scanf("%d",&n)!=EOF){
        loc=0;
        Node *T=NULL; // 建立一個根結點 
        for(int i=0;i<n;i++){
            int x;
            scanf("%d",&x);
            T=Insert(T,x);  // 返回樹的根結點 
        } 

        /*對根結點的父節點的判斷有點投機取巧,應在函數中判斷所訪問結點是否爲樹的根結點,是則打印-1*/
        printf("%d的父結點是:-1\n",Tree[0].data);  // 寫者這裏直接跳過判斷,因爲二叉排序樹的首節點必爲根結點 

        for(int i=1;i<loc;i++){  // 依次遍歷樹,找到並輸出根結點 
            findParent(T,Tree[i].data); 
        }
    } 
    return 0;
}

執行結果:
這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章