二叉樹的遞迴建立

來源:互聯網
上載者:User

標籤:先序和中序 中序和後序建立

1、樹

        (1)、樹形結構本身具有遞迴的性質(在其後的編程中體現的淋漓盡致)!

        樹是一種非常重要的非線性結構。

        (2)、幾個概念:結點的度,就是分支個數(孩子個數);

                                 樹的度,結點度中最大的(孩子最多的);

                                非葉子結點,度 > 0 (有孩子結點);

                                葉子結點,度為0的 (沒有孩子結點);

                                樹的高度,從1開始算;

        (3)、為什麼要學習二叉樹?

                     原因:所有的樹形結構(包括森林)都可以轉化為二叉樹。二叉樹是樹形結構的基礎,

只有學好了二叉樹才能學好其它的。

2、二叉樹

        (1)、二叉樹分左右,所以又叫做有序樹。

650) this.width=650;" src="http://s1.51cto.com/wyfs02/M00/85/81/wKiom1emjgWTPNQEAAAR7Zj3jCg237.png-wh_500x0-wm_3-wmp_4-s_57316320.png" title="QQ20160807092450.png" alt="wKiom1emjgWTPNQEAAAR7Zj3jCg237.png-wh_50" />

        (2)、二叉樹中的度 <= 2,度都為1時,就退化為鏈表了,

        (3)、每一層最多結點個數:2^(i-1);是偶數個,i代表層數(從1開始);

                整棵樹的最多結點個數:2^k - 1; 是技術個(因為除了根節點只有一個,其它每層都是偶數個),k代表層數(從1開始);

        (4)、n(0) = n(2) + 1;  度為0的葉子結點等於度為2的結點加1;

        (5)、滿二叉樹和完全二叉樹:

650) this.width=650;" src="http://s4.51cto.com/wyfs02/M01/85/82/wKiom1emk3-w4RgcAAAhd33ZoLo233.png-wh_500x0-wm_3-wmp_4-s_2786281145.png" title="QQ20160807094819.png" alt="wKiom1emk3-w4RgcAAAhd33ZoLo233.png-wh_50" />

        滿二叉樹一定是完全二叉樹,完全二叉樹不一定是滿二叉樹;

        完全二叉樹有N個結點的高度:[log2^N](向下取整) + 1;

3、二叉樹的儲存形式:

        (1)、線性儲存,數組儲存,------->針對完全二叉樹好,

        (2)、鏈式儲存-------------->針對普通二叉樹;

4、二叉樹的建立:

        我認為有9種建立方式:寫出先序序列,

                 從鍵盤輸入的建立方案:參數和傳回值建立            2

                 根據(檔案)字串的傳入:參數和傳回值建立          2

                由先序和中序建立                                                   2

                由中序和後序建立                                                   2

                以上的都是通過遞迴建立二叉樹,形式方法,大同小異!

                以後我還會寫上非遞迴建立二叉樹,不在浪費多餘以#代替的空間  1

5、建立二叉樹:

        均由C++實現,寫出先序序列,在進行建立

        (1)、因為樹形結構本身具有遞迴性質,所以以下均是遞迴建立,以後我會寫非遞迴建立的。

        (2)、遞迴建立符合數學思維和邏輯,但是容易造成棧溢出,並且遞迴佔用系統資源,好寫但不明智的做法,

                我認為寫程式應該盡量避免遞迴的做法!!

        (3)、這裡寫出先序建立,例如:"ABC##DE##F##G#H##"字串建立,根據#判斷是否開闢空間!

        (4)、先序和後序一般不用於建立二叉樹,因為存在歧義:

650) this.width=650;" src="http://s1.51cto.com/wyfs02/M02/85/83/wKiom1emwIHAo6SmAAAUx_nV8Fk701.png-wh_500x0-wm_3-wmp_4-s_1642608019.png" title="QQ20160807130027.png" alt="wKiom1emwIHAo6SmAAAUx_nV8Fk701.png-wh_50" />

由先序和中序,中序和後序建立二叉樹是重點:

template<typename Type>  //中序和後序建立void BinTree<Type>::createBinTree_1(BinTreeNode<Type> *&t, const char *LVR, const char *LRV, int n){    if(n == 0){   //字串長度為0,建立空樹        t = NULL;        return;    }    int k = 0;    while(LVR[k] != LRV[n-1]){  //找出根結點的下標        k++;    }    t = new BinTreeNode<Type>(LVR[k]);  //建立根結點            createBinTree_1(t->rightChild, LVR+k+1, LRV+k, n-k-1); //先建立右子樹,中跨k+1個,後跨k個,到底右邊,右邊一共n-k-1個節點;    createBinTree_1(t->leftChild, LVR, LRV, k);//在建立左子樹,從頭開始,一共k個;}template<typename Type>  //先序和中序建立void BinTree<Type>::createBinTree(BinTreeNode<Type> *&t, const char *VLR, const char *LVR, int n){    if(n == 0){   //要是長度為0,則建立空樹        t = NULL;        return;    }    int k = 0;    while(LVR[k] != VLR[0]){  //由先序找到在中序中的位置k;        k++;    }    t = new BinTreeNode<Type>(LVR[k]);  //首先建立根    createBinTree(t->leftChild, VLR+1, LVR, k);  //建立左邊,跨過根, 中序, 根左邊k個節點;    createBinTree(t->rightChild, VLR+k+1, LVR+k+1, n-k-1);//建立右邊,肯定都得+K+1,根右邊n-k-1個結點;}


都是遞迴建立的,好想,畫畫圖就理解了,代碼如下:

#ifndef _BIN_TREE_H_   //先行編譯條件宏#define _BIN_TREE_H_#include<iostream>    //引入標頭檔using namespace std;template<typename Type>  //聲明友元類class BinTree;template<typename Type>class BinTreeNode{      //二叉樹結點的模板類    friend class BinTree<Type>;  //可以調用其私人資料成員public:    BinTreeNode() : data(Type()), leftChild(NULL), rightChild(NULL){}  //預設的建構函式    BinTreeNode(Type value, BinTreeNode<Type> *left = NULL, BinTreeNode<Type> *right = NULL) :    data(value), leftChild(left), rightChild(right){}  //帶參數的建構函式    ~BinTreeNode(){}  //解構函式暫時什麼都不做private:    Type data;   //資料    BinTreeNode *leftChild; //左孩子指標    BinTreeNode *rightChild;  //右孩子指標};////////////////////////////////////////////////////以上是結點類型template<typename Type>class BinTree{       //二叉樹的模板類public:    BinTree() : root(NULL){}  ////預設的建構函式    BinTree(Type ref) : root(NULL), refval(ref){} //帶參數的建構函式    ~BinTree(){}public:   //以下四個是供外部調用的介面   函式宣告,類外定義    void createBinTree();  //鍵盤輸入建立    void createBinTree(const char *str);  //主函數傳字串建立    void createBinTree(const char *VLR, const char *LVR, int n); //先序和中序建立    void createBinTree_1(const char *LVR, const char *LRV, int n);  //中序和後序建立protected :  //以下6個是保護方法,外部不能直接存取,供內建函式的調用  函式宣告,類外定義    void createBinTree(BinTreeNode<Type> *&t);      BinTreeNode<Type>* createBinTree_1();    void createBinTree(const char *&str, BinTreeNode<Type> *&t);    BinTreeNode<Type>* createBinTree_1(const char *&str);    void createBinTree(BinTreeNode<Type> *&t, const char *VLR, const char *LVR, int n);    void createBinTree_1(BinTreeNode<Type> *&t, const char *LVR, const char *LRV, int n);private:    BinTreeNode<Type> *root;    //根節點(要是C語言的話,的弄一個指向根節點的指標);    Type               refval;  //‘#‘標誌,建立多餘空間,利用率比較低。};////////////////////////////////////////////////////////////以上是二叉樹的類型    template<typename Type>   //類外函數的定義void BinTree<Type>::createBinTree(){    //createBinTree(root);     root = createBinTree_1();  //調用內部防寫保護的方法實現}template<typename Type>void BinTree<Type>::createBinTree(const char *str){//    createBinTree(str, root);    root = createBinTree_1(str);}template<typename Type>void BinTree<Type>::createBinTree(const char *VLR, const char *LVR, int n){    createBinTree(root, VLR, LVR, n);}template<typename Type>void BinTree<Type>::createBinTree_1(const char *LVR, const char *LRV, int n){    createBinTree_1(root, LVR, LRV, n);}////////////////////////////////////////////////////////////以上是類外調用保護方法//其下就是具體的建立過程template<typename Type>  //中序和後序建立void BinTree<Type>::createBinTree_1(BinTreeNode<Type> *&t, const char *LVR, const char *LRV, int n){    if(n == 0){   //字串長度為0,建立空樹        t = NULL;        return;    }    int k = 0;    while(LVR[k] != LRV[n-1]){  //找出根結點的下標        k++;    }    t = new BinTreeNode<Type>(LVR[k]);  //建立根結點            createBinTree_1(t->rightChild, LVR+k+1, LRV+k, n-k-1); //先建立右子樹,中跨k+1個,後跨k個,到底右邊,右邊一共n-k-1個節點;    createBinTree_1(t->leftChild, LVR, LRV, k);//在建立左子樹,從頭開始,一共k個;}template<typename Type>  //先序和中序建立void BinTree<Type>::createBinTree(BinTreeNode<Type> *&t, const char *VLR, const char *LVR, int n){    if(n == 0){   //要是長度為0,則建立空樹        t = NULL;        return;    }    int k = 0;    while(LVR[k] != VLR[0]){  //由先序找到在中序中的位置k;        k++;    }    t = new BinTreeNode<Type>(LVR[k]);  //首先建立根    createBinTree(t->leftChild, VLR+1, LVR, k);  //建立左邊,跨過根, 中序, 根左邊k個節點;    createBinTree(t->rightChild, VLR+k+1, LVR+k+1, n-k-1);//建立右邊,肯定都得+K+1,根右邊n-k-1個結點;}template<typename Type>  //返回指標root接受,字串建立BinTreeNode<Type>* BinTree<Type>::createBinTree_1(const char *&str){    BinTreeNode<Type> *t;    if(refval == *str){        t = NULL;    }else{        t = new BinTreeNode<Type>(*str);        t->leftChild = createBinTree_1(++str);        t->rightChild = createBinTree_1(++str);    }    return t;}template<typename Type>  //引用直接更改root,字串建立void BinTree<Type>::createBinTree(const char *&str, BinTreeNode<Type> *&t){    if(*str == refval){            t = NULL;     }else{        t = new BinTreeNode<Type>(*str);        createBinTree(++str, t->leftChild);  //前加,後加不一樣!!!在這裡,就是傳引用,保證每次字串都是往後走的        createBinTree(++str, t->rightChild);    }}template<typename Type>  //返回指標root接受, 鍵盤輸入先序建立BinTreeNode<Type>* BinTree<Type>::createBinTree_1(){    Type createData;    cin>>createData;    BinTreeNode<Type> *t;    if(refval == createData){        t = NULL;    }else{        t = new BinTreeNode<Type>(createData);        t->leftChild = createBinTree_1();        t->rightChild = createBinTree_1();    }    return t;}template<typename Type>  //引用直接更改root,根據先根序建立二叉樹void BinTree<Type>::createBinTree(BinTreeNode<Type> *&t){    Type createData;    cin>>createData;  //鍵盤輸入建立序列    if(refval == createData){  //與#相同,則賦空,相當於給左右孩子賦空        t = NULL;    }else{        t = new BinTreeNode<Type>(createData);  //申請空間        createBinTree(t->leftChild);  //左遞迴建立        createBinTree(t->rightChild);  //右遞迴建立    }}

              

二叉樹的遞迴建立

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.