二叉樹,遞歸實現

暑假的時候看了一次二叉樹,看的暈暈乎乎的就放下了,現在重新看了一遍,理解了二叉樹,覺得這篇博客不錯,首先感謝原博主,在這裏分享出來:

不過學習之前要了解的預備知識:樹的概念;二叉樹的存儲結構;二叉樹的遍歷方法。。

    二叉樹的存儲結構主要了解二叉鏈表結構,也就是一個數據域,兩個指針域,(分別爲指向左右孩子的指針),從下面程序1,二叉樹的存儲結構可以看出。

    二叉樹的遍歷方法:主要有前序遍歷,中序遍歷,後序遍歷,層序遍歷。

如這樣一個二叉樹: 


它的前序遍歷順序爲:ABDGHCEIF(規則是先是根結點,再前序遍歷左子樹,再前序遍歷右子樹)

它的中序遍歷順序爲:GDHBAEICF(規則是先中序遍歷左子樹,再是根結點,再是中序遍歷右子樹)

它的後序遍歷順序爲:GHDBIEFCA(規則是先後序遍歷左子樹,再是後序遍歷右子樹,再是根結點)

如果不懂就查看一下相關數據結構的書籍

1.二叉樹存貯結構:

複製代碼
//二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子)

typedef  struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;
複製代碼
 2,首先要建立一個二叉樹,建立二叉樹必須要瞭解二叉樹的遍歷方法。

複製代碼
//二叉樹的建立,按前序遍歷的方式建立二叉樹,當然也可以以中序或後序的方式建立二叉樹
void CreateBiTree(BiTree *T)
{
    ElemType ch;
    cin >> ch;
    if (ch == '#')
        *T = NULL;  //保證是葉結點
    else
    {
        *T = (BiTree)malloc(sizeof(BiTNode));
        //if (!*T)
            //exit(OVERFLOW); //內存分配失敗則退出。
        (*T)->data = ch;//生成結點
        CreateBiTree(&(*T)->lchild);//構造左子樹
        CreateBiTree(&(*T)->rchild);//構造右子樹    
    }
}
複製代碼

3.二叉樹的遍歷(遞歸方式,非遞歸方式見下篇:樹(二叉樹)的建立和遍歷算法(二)):

主要有三種方法:

複製代碼
/遞歸方式前序遍歷二叉樹
void PreOrderTraverse(BiTree T, int level)
{
    if (T == NULL)
        return;
/*此處表示對遍歷的樹結點進行的操作,根據你自己的要求進行操作,這裏只是輸出了結點的數據*/ //operation1(T->data); operation2(T->data, level); //輸出了層數 PreOrderTraverse(T->lchild, level + 1); PreOrderTraverse(T->rchild, level + 1); } //遞歸方式中序遍歷二叉樹 void InOrderTraverse(BiTree T,int level) { if(T==NULL) return; InOrderTraverse(T->lchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 InOrderTraverse(T->rchild,level+1); } //遞歸方式後序遍歷二叉樹 void PostOrderTraverse(BiTree T,int level) { if(T==NULL) return; PostOrderTraverse(T->lchild,level+1); PostOrderTraverse(T->rchild,level+1); //operation1(T->data); operation2(T->data, level); //輸出了層數 }
複製代碼
4.完整代碼:

複製代碼
#include<iostream>
#include<stdlib.h>
using namespace std;

typedef char ElemType;

//二叉樹的二叉鏈表結構,也就是二叉樹的存儲結構,1個數據域,2個指針域(分別指向左右孩子)

typedef  struct BiTNode
{
    ElemType data;
    struct BiTNode *lchild, *rchild;
}BiTNode, *BiTree;

//二叉樹的建立,按前序遍歷的方式建立二叉樹,當然也可以以中序或後序的方式建立二叉樹
void CreateBiTree(BiTree *T)
{
    ElemType ch;
    cin >> ch;
    if (ch == '#')
        *T = NULL;  //保證是葉結點
    else
    {
        *T = (BiTree)malloc(sizeof(BiTNode));
        //if (!*T)
            //exit(OVERFLOW); //內存分配失敗則退出。
        (*T)->data = ch;//生成結點
        CreateBiTree(&(*T)->lchild);//構造左子樹
        CreateBiTree(&(*T)->rchild);//構造右子樹    
    }
}
//表示對遍歷到的結點數據進行的處理操作,此處操作是將樹結點前序遍歷輸出
void operation1(ElemType ch)
{
    cout << ch << " ";
}
//此處在輸出的基礎上,並輸出層數
void operation2(ElemType ch, int level)
{
       cout << ch << "在第" << level << "" << endl;
}


//遞歸方式前序遍歷二叉樹
void PreOrderTraverse(BiTree T, int level)
{
    if (T == NULL)
        return;
/*此處表示對遍歷的樹結點進行的操作,根據你自己的要求進行操作,這裏只是輸出了結點的數據*/
    //operation1(T->data);
    operation2(T->data, level); //輸出了層數

    PreOrderTraverse(T->lchild, level + 1);
    PreOrderTraverse(T->rchild, level + 1);
}

//遞歸方式中序遍歷二叉樹

void InOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
InOrderTraverse(T->lchild,level+1);

//operation1(T->data);
operation2(T->data, level); //輸出了層數

InOrderTraverse(T->rchild,level+1);
}

//遞歸方式後序遍歷二叉樹

void PostOrderTraverse(BiTree T,int level)
{
if(T==NULL)
return;
PostOrderTraverse(T->lchild,level+1);
PostOrderTraverse(T->rchild,level+1);

//operation1(T->data);
operation2(T->data, level); //輸出了層數
}


int main()
{
    int level = 1; //表示層數
    BiTree T = NULL;
    cout << "請以前序遍歷的方式輸入擴展二叉樹:"; //類似輸入AB#D##C##
    CreateBiTree(&T);// 建立二叉樹,沒有樹,怎麼遍歷

    cout << "遞歸前序遍歷輸出爲:" << endl;
    PreOrderTraverse(T, level);//進行前序遍歷,其中operation1()和operation2()函數表示對遍歷的結點數據進行的處理操作
    cout << endl;

    cout << "遞歸中序遍歷輸出爲:" << endl;
    InOrderTraverse(T, level);
    cout << endl;

    cout << "遞歸後序遍歷輸出爲:" << endl;
    PostOrderTraverse(T, level);
    cout << endl;

    return 0;
}
複製代碼

注意:這裏有幾個知識點補充下:

(1)建立二叉樹時,這裏是以前序遍歷的方式,輸入的是擴展二叉樹,也就是要告訴計算機什麼是葉結點,否則將一直遞歸,當輸入“#”時,指針指向NULL,說明是葉結點。

如圖爲擴展二叉樹:(前序遍歷爲:ABDG##H###CE#I##F##)


(2)operation1( )函數只是對各個結點的輸出;

        operation2( )函數不僅輸出了各個結點,同時輸出了結點所在的層數。(調試時可以只先運行一個)

5.運行結果

只是運行了operation2( )函數,有層數輸出:


或者運行只運行operation1( )函數


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