c實現樹(二叉樹)的創建和遍歷算法(一)(前序,中序,後序)

   最近學習樹的概念,有關二叉樹的實現算法記錄下來。。。html

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

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

    二叉樹的遍歷方法:主要有前序遍歷,中序遍歷,後序遍歷,層序遍歷。(層序遍歷下一篇再講,本篇主要講的遞歸法)算法

   下篇主要是非遞歸遍歷,以後會有c++模板實現  二叉樹 二叉搜索樹(用於動態查找)數據結構

如這樣一個二叉樹:
函數

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

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

它的後序遍歷順序爲: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( )函數

相關文章
相關標籤/搜索