題解——二叉樹的基本操做

題解——二叉樹的基本操做

題目連接:傳送門ios

描述

採用括號表示法的字符串建立二叉鏈表表示的二叉樹,實現二叉樹的基本運算,以下:算法

(1)用括號表示法輸出二叉樹;數據結構

(2)輸出節點的左、右孩子節點值;函數

(3)輸出二叉樹的深度;spa

(4)輸出二叉樹的寬度;.net

(5)輸出二叉樹的節點個數;指針

(6)輸出二叉樹的葉子節點個數;code

(7)釋放二叉樹。blog

輸入

兩行數據:
第一行:用括號表示法表示二叉樹的字符串;
第二行:要求輸出的是括號表示法裏的第幾個節點的左、右孩子節點值;

ci

輸出

按照程序要求輸出。
其中:

  • 輸出節點的左、右孩子節點值;
  • 若無,則輸出:no leftchild no rightchild

樣例輸入

A(B(D,E(G,)),C(,F))
2

樣例輸出

A(B(D,E(G)),C(,F))
D E
4
3
7
3

提示

參考實驗題7.1

題解

基本操做(1)(3)(4)(5)(6)(7)能夠在以前的博客裏找到解析:數據結構與算法——二叉樹

核心難點或許是(2)

輸出節點的左、右孩子節點值;

輸入的時候,第一行咱們輸入的是括號表達式,第二行還輸入了一個數n,這個數就是在(2)裏起做用——輸出括號表達式中第n個結點的左右孩子

因此咱們要作的就是:

  1. 找到第n個結點
  2. 輸出它的左右孩子

咱們能夠在建立樹的同時,也就是在CreateTree函數裏面,作一個計數器,記錄當前進入樹的結點是第幾個進入樹的結點,若是當前的結點就是第n個,那咱們把它保存起來。最後,再輸出它。

按上面的思路,咱們:

  • 設定一個全局變量n,以確保在主函數輸入n後,能夠在其餘函數裏直接訪問n的值;
  • 定義一個BTNode型的指針變量res,用來存儲找到的第n個結點
  • 修改CreateTree函數,添加計數器和判斷條件:
int n,num=0; //num是計數器,把它也定義爲全局變量的好處是,它順便記錄了樹的結點個數,這樣(5)就能夠直接輸出num了

BTNode *res=new BTNode(); //用於記錄第n個結點

void CreateBTree(BTNode *&bt,char *str){ 
    stack<BTNode*> st;
    bt=NULL;
    int k;
    BTNode *p=NULL;
    int len=strlen(str);
    for(int i=0;i<len;i++){ 
        if(str[i]=='('){ 
            k=1;
            st.push(p);
            continue;
        }
        else if(str[i]==')'){ 
            st.pop();
            continue;
        }
        else if(str[i]==','){ 
            k=2;
            continue;
        }
        else{ 
            p=new BTNode();
            p->data=str[i];
            p->lc=p->rc=NULL;
            if(bt==NULL){ 
                bt=p;
                num++; //計數器記錄
                if(num==n) //判斷
                    res=p; //保存
            }
            else{ 
                if(k==1)
                    st.top()->lc=p;
                else if(k==2)
                    st.top()->rc=p;
                num++; //計數器記錄
                if(num==n) //判斷
                    res=p; //保存
            }
        }
    }
}

須要注意的是,爲何必定要保存起來,而不是找到就輸出?

由於剛找到第n個結點的時候,它剛進樹,尚未孩子,因此這時候你就算要輸出,也沒啥好輸出的,只能把它存下來,等它有孩子了你再輸出。它何時有孩子?全建立完了就有孩子了。

完整代碼參考:
不能夠直接抄啊!

#include <iostream>
#include <stack>
#include <cstring>
#define ElemType char
using namespace std;
struct BTNode{  //"二叉樹點"
    ElemType data; //用define把char定義爲ElemType
    BTNode *lc,*rc; //lc是"left child"左孩子,rc是"right child"右孩子
};

int n,num=0; //第n個結點,num是計數器
BTNode *res=new BTNode(); //用於記錄第n個結點
void CreateBTree(BTNode *&bt,char *str){ 
    stack<BTNode*> st; //STL的棧,類型爲BTNode的指針
    bt=NULL; //根結點初始化爲空
    int k; //用k記錄左右兒子,1爲左,2爲右
    BTNode *p=NULL; //用p存儲讀取到的字符
    int len=strlen(str); //字符串str的長度爲len
    for(int i=0;i<len;i++){ 
        if(str[i]=='('){ 
            k=1; //k計爲左兒子
            st.push(p); //入棧
            continue;
        }
        else if(str[i]==')'){ 
            st.pop(); //出棧
            continue; //繼續日後看
        }
        else if(str[i]==','){ 
            k=2; //k計爲右兒子
            continue;
        }
        else{ 
            p=new BTNode(); //爲p申請空間
            p->data=str[i]; //賦值
            p->lc=p->rc=NULL;
            if(bt==NULL){  //若是bt爲空,表明p爲最開始的根結點
                bt=p;
                num++;
                if(num==n)
                    res=p;
            }
            else{ 
                if(k==1) //以前讀取到左括號,說明p是左孩子
                    st.top()->lc=p;
                else if(k==2) //以前讀取到逗號,說明p是右孩子
                    st.top()->rc=p;
                num++;
                if(num==n)
                    res=p;
            }
        }
    }
}

void DispBTree(BTNode *bt){  //輸出
    if(bt!=NULL){ 
        cout<<bt->data;
        if(bt->lc!=NULL|| bt->rc != NULL)
        { 
            cout<<'(';
            DispBTree(bt->lc);
            if(bt->rc != NULL)
                cout<<',';
            DispBTree(bt->rc);
            cout<<')';
        }
    }
}

int BTHeight(BTNode *bt){  //求高度
    int lch, rch; //左子樹深度lch和右子樹深度rch
    if(bt==NULL) return 0; //若是是空的,就說明沒有長度,返回0
    else{ 
        lch=BTHeight(bt->lc); //左子樹的深度
        rch=BTHeight(bt->rc); //右子樹的深度
        if(lch>rch)return lch+1;
        else return rch+1;
    }
}

int Count[10010];
void WidConut(BTNode *bt, int dep){   //寬度
    if(bt==NULL)
        return ;
    Count[dep]++;
    dep++;
    WidConut(bt->lc,dep);
    WidConut(bt->rc,dep);
}

int NodeCount(BTNode *bt){  //求結點個數
    int num1,num2;
    if(bt==NULL)
        return 0;
    else{ 
        num1=NodeCount(bt->lc); //左子樹的結點個數
        num2=NodeCount(bt->rc); //右子樹的結點個數
        return num1+num2+1;
    }
}

int LeafCount(BTNode *bt){  //求葉子結點個數
    int num1,num2;
    if(bt==NULL)
        return 0;
    else if(bt->lc==NULL&&bt->rc==NULL)
        return 1;
    else{ 
        num1=LeafCount(bt->lc); //左子樹的葉子結點
        num2=LeafCount(bt->rc); //右子樹的葉子結點
        return num1+num2;
    }
}

void DestoryBTree(BTNode *&bt){  //釋放
    if(bt!=NULL){  //bt只要不是NULL,就把它的孩子叫來
        DestoryBTree(bt->lc); //讓它叫左孩子
        DestoryBTree(bt->rc); //讓它叫右孩子
        delete bt; //嫩死它
    }
}

int main()
{ 
    BTNode *bt;
    char str[1000];
    cin>>str;
    cin>>n;
    CreateBTree(bt,str);
    DispBTree(bt);
    cout<<endl;
    if(res->lc!=NULL)
        cout<<res->lc->data<<" ";
    else cout<<"no leftchild ";
    if(res->rc!=NULL)
        cout<<res->rc->data<<endl;
    else cout<<"no rightchild"<<endl;
    cout<<BTHeight(bt)<<endl;
    WidConut(bt,0);
    
    int wid=0;
    for(int i=0;Count[i]!=0;i++)
        wid=max(wid,Count[i]);
    cout<<wid<<endl;
    cout<<NodeCount(bt)<<endl;
    //cout<<"num="<<num<<endl; //"輸出長度"能夠直接用num,去掉注視符號試試
    cout<<LeafCount(bt);
    DestoryBTree(bt);
    return 0;
}
相關文章
相關標籤/搜索