1. 程式人生 > >二叉樹的基本操作 C++程式碼實現

二叉樹的基本操作 C++程式碼實現

首先定義節點

typedef struct BTree
{
    int    value;
    struct BTree *lchild;
    struct BTree *rchild;
}BTree;

前序遞迴建立二叉樹

/*
**num 前序序列
**index 下標
*/
BTree *CreateBTree(BTree *node,int *num,int& index)
{
    if(num[index] == 0)
        return NULL;
    else
    {
        node = new BTree;
        node -> value = num[index
]; node -> lchild = CreateBTree(node->lchild,num,++index); node -> rchild = CreateBTree(node->rchild,num,++index); } return node; }

幾種遍歷

遞迴--前序遍歷

void preOrder(BTree * root)
{
    if(root == NULL)
        return;
    cout << root -> value <<
" ";  //先輸出樹的根節點的值 preOrder(root -> lchild); //遞迴 左子樹 preOrder(root -> rchild); //遞迴 右子樹 }

非遞迴--前序遍歷

void preOrder_dxm(BTree * root)
{
    stack<BTree*> S;
    BTree *p = root;
    while(p != NULL || !S.empty())
    {
        while(p != NULL)
        {
            cout
<< p -> value << " "; S.push(p); p = p -> lchild; } if(!S.empty()) { S.pop(); if(S.empty()) return ; p = S.top(); S.pop(); p = p -> rchild; } } }

遞迴--中序遍歷

void inOrder(BTree * root)
{
    if(root == NULL)
        return;
    inOrder(root -> lchild);
    cout << root -> value << " ";
    inOrder(root -> rchild);
}

非遞迴--中序遍歷

void inOrder_dxm(BTree * root)
{
    stack<BTree*> S;
    BTree *p = root;
    while(p != NULL || !S.empty())
    {
        while(p != NULL)
        {
            //cout << p -> value << " ";
            S.push(p);
            p = p -> lchild;
        }
        if(!S.empty())
        {
            p = S.top();
            cout << p -> value << " ";
            S.pop();
            if(S.empty())
                return ;
            //S.pop();
            p = S.top();
            cout << p -> value << " ";
            S.pop();
            p = p -> rchild;
        }
    }
}

遞迴--後序遍歷

void postOrder(BTree * root)
{
    if(root == NULL)
        return;
    postOrder(root -> lchild);
    postOrder(root -> rchild);
    cout << root -> value << " ";
}

非遞迴--後序遍歷

void postOrder_dxm(BTree * root)
{
    stack<BTree*> S;
    BTree *cur;
    BTree *pre = NULL;
    S.push(root);
    while(!S.empty())
    {
        cur = S.top();
        if((cur -> lchild == NULL && cur -> rchild == NULL) || 
           (pre != NULL && (pre == cur -> lchild || pre == cur ->rchild)))
        {
            cout << cur -> value << " ";
            S.pop();
            pre = cur;
        }
        else
        {
            if(cur -> rchild != NULL)
                S.push(cur -> rchild);
            if(cur -> lchild != NULL)
                S.push(cur -> lchild);
        }
    }
}

求二叉樹的深度

int getdepth(BTree *root)
{
    if(root == NULL)
        return 0;
    int lchild_depth = getdepth(root -> lchild);
    int rchild_depth = getdepth(root -> rchild);
    return max(lchild_depth,rchild_depth) + 1;
}

求二叉樹葉子節點的個數

int getleaves(BTree *root)
{
    if(root == NULL)
        return 0;
    if(root -> lchild == NULL && root -> rchild == NULL)
        return 1;    
    return 1 + getleaves(root -> lchild) + getleaves(root -> rchild);
}

樹狀列印二叉樹

void print(BTree *root,int h)
{
    if(root != NULL)
    {
        print(root -> rchild,h+1);
        for(int i=0; i<h; i++)
            cout << "   ";
        cout << root -> value;
        print(root -> lchild,h+1);
    }
    cout << endl;
}

主函式

int main()
{
    int num[] = {1,2,4,8,0,0,9,0,0,5,10,0,0,11,0,0,3,6,12,0,0,13,0,0,7,14,0,0,15,0,0};
    BTree *root = NULL;
    int index = 0;
    root = CreateBTree(root,num,index);

    cout << "前序非遞迴遍歷: " << endl;
    preOrder_dxm(root);
    cout << endl;

    cout << "中序遞迴遍歷: " << endl;
    inOrder_dxm(root);
    cout << endl;

    cout << "後續非遞迴遍歷: " << endl;
    postOrder_dxm(root);
    cout << endl << endl;;

    cout << "此二叉樹的形狀為: " << endl;
    print(root,1);

    return 0;
}

輸出結果

這裡寫圖片描述

由給定二叉樹的兩種序列建立二叉樹

前序序列:根在前,且左孩子在右孩子前
中序序列:根在中間,左邊為左孩子,右邊為右孩子
後序序列:根在最後,且左孩子在右孩子前

根據二叉樹前序序列和中序序列建立二叉樹:

  1. 前序序列的第一個元素就是二叉樹的根節點
  2. 在中序序列中找到根節點,根據根節點將中序序列分為兩部分:此節點左邊的是左子樹的中序序列,右邊是右子樹的中序序列;
  3. 將除去根節點的前序序列分為兩部分:左子樹在前,剩下為右子樹
  4. 遞迴建立左右子樹
/*************************************************************************
    > File Name: 中序&先序建立二叉樹.cpp
    > Author: Tanswer
    > Mail: [email protected]
    > Created Time: 2016年10月24日 星期一 17時33分24秒
 ************************************************************************/

#include <iostream>
#include <string>
#include <vector>
#include <algorithm>

using namespace std;
typedef struct BTree
{
    char value;
    struct BTree *lchild;
    struct BTree *rchild;
}BTree;


BTree *Created(BTree *root,string pre,string in)
{

    if(pre.length() == 0)
    {
        root = NULL;
        return NULL;
    }
    //前序的第一個值 為 根
    int root_value = pre[0];
    //找到根在中序中的位置 :下標
    int index = in.find(root_value);
    //左孩子的中序序列
    string lchild_in = in.substr(0,index);
    //右孩子的中序序列
    string rchild_in = in.substr(index+1);
    //左孩子結點個數
    int lchild_length = lchild_in.length();
    //右孩子結點個數
    int rchild_length = rchild_in.length();
    //左孩子的前序序列
    string lchild_pre = pre.substr(1,lchild_length);
    //右孩子的前序序列
    string rchild_pre = pre.substr(1+lchild_length);

    root = new BTree;
    if(root != NULL)
    {
        root -> value = root_value;
        //root -> lchild = new BTree;
        root -> lchild = Created(root -> lchild,lchild_pre,lchild_in);
        //root -> rchild = new BTree;
        root -> rchild = Created(root -> rchild,rchild_pre,rchild_in);
    }
    return root;
}

/*樹狀列印二叉樹*/
void print(BTree *root,int h)
{
    if(root != NULL)
    {
        print(root -> rchild,h+1);
        for(int i=0; i<h; i++)
            cout << "   ";
        cout << root -> value;
        print(root -> lchild,h+1);
    }
    cout << endl;
}

int main()
{
    cout << "先序序列為:  ABDECFG" << endl;
    cout << "中序序列為:  DBEAFCG" << endl;
    cout << "二叉樹為: " << endl;;
    string pre = "ABDECFG";
    string in = "DBEAFCG";
    BTree *root = NULL;
    root = Created(root,pre,in);
    print(root,1);

    return 0;
}

輸出結果:
   
這裡寫圖片描述

根據二叉樹後序序列和中序序列建立二叉樹:

過程和上面的類似,就不再寫了,直接上程式碼

BTree *Created(BTree *root,string post,string in)
{

    if(post.length() == 0)
    {
       root = NULL;
        return NULL;
    }

    /*後序序列的結點個數*/
    int size = post.size();

    //後序的最後一個值 為 根
    int root_value = post[size - 1];
    //找到根在中序中的位置 :下標
    int index = in.find(root_value);
    //左孩子的中序序列
    string lchild_in = in.substr(0,index);
    //右孩子的中序序列
    string rchild_in = in.substr(index+1);
    //左孩子結點個數
    int lchild_length = lchild_in.length();
    //右孩子結點個數
    int rchild_length = rchild_in.length();
    //左孩子的後序序列
    string lchild_post = post.substr(0,lchild_length);
    //右孩子的後序序列
    string rchild_post = post.substr(lchild_length,rchild_length);

    root = new BTree;
    if(root != NULL)
    {
        root -> value = root_value;

        root -> lchild = Created(root -> lchild,lchild_post,lchild_in);

        root -> rchild = Created(root -> rchild,rchild_post,rchild_in);
    }
    return root;
}