求解二叉樹的深度

求解二叉樹的深度可以採用遞歸和非遞歸的方式。遞歸實現的代碼很是簡單、易懂。而非遞歸實現代碼較複雜。

遞歸求解二叉樹深度


遞歸的結束條件有兩個:1.該節點爲NULL,返會0;2.當前節點的左右字數深度均求出,返會最大值
下面是遞歸實現的代碼:

//遞歸求解二叉樹的深度
int BTreeDepth(BTree *root)
{
    if (root == NULL)
        return 0;

    int left = 1 + BTreeDepth(root->lChild);
    int right = 1 + BTreeDepth(root->rChild);

    return left>right?left:right;
}

非遞歸求解二叉樹深度


同樣利用棧來實現求解二叉樹的深度,棧最大時即爲二叉樹的深度。這裏對二叉樹節點的數據結構進行包裝:
二叉樹的結構體爲:

struct BTree
{
    int data;
    BTree* lChild;
    BTree* rChild;

    BTree():data(0),lChild(NULL),rChild(NULL){};
};

對該結構體進行增加信息,增加兩個變量分別表示該節點的左右孩子節點是否被訪問過:

struct StackBTree
{
    BTree *bTree;
    int lFlag;//標記左孩子是否被訪問過,0:未訪問 1:已訪問
    int rFlag;;//標記右孩子是否被訪問

    StackBTree():lFlag(0),rFlag(0),bTree(NULL){};
};

利用該結構體求解二叉樹深度的思路如下:

  • 判斷根節點是否爲空,若爲空則,返回0;若不爲空,則將根節點入棧;
  • while循環。若棧不爲空,則進程while循環
  • 取棧頂元素
  • 一種情況:若該元素的左孩子非空,且左孩子未被訪問過;
    • 標記該節點的左孩子被訪問過
    • 將該節點的左孩子入棧
  • 另一種情況:若該元素的左孩子被訪問過或者左孩子爲空、並且右孩子非空,且右孩子未被訪問過;
    • 標記該節點右孩子被訪問過
    • 將該節點的右孩子入棧
  • 最後一種情況:
    • depth等於depth和棧大小中的最大值
    • 棧頂元素出棧
  • 轉到第三步
  • 返回depth,保存深度的變量

該方法主要是通過標記訪問過的變量,利用棧的深度來計算二叉樹的深度。具體代碼如下所示:

#pragma once
#ifndef BTREE_H
#define BTREE_H

#include <iostream>
#include <stack>

using namespace std;

struct BTree
{
    int data;
    BTree* lChild;
    BTree* rChild;

    BTree():data(0),lChild(NULL),rChild(NULL){};
};

//構造二叉樹
void InitBTree(BTree *root)
{
    root->data = 1;
    root->lChild = new BTree();
    root->lChild->data = 2;
    root->rChild = new BTree();
    root->rChild->data = 3;

    root->lChild->lChild = new BTree();
    root->lChild->lChild->data = 4;
    root->lChild->rChild = new BTree();
    root->lChild->rChild->data = 5;

    root->rChild->lChild = new BTree();
    root->rChild->lChild->data = 6;
    root->rChild->rChild = new BTree();
    root->rChild->rChild->data = 7;

    root->rChild->lChild->lChild = new BTree();
    root->rChild->lChild->lChild->data = 8;
    root->rChild->lChild->lChild->lChild = new BTree();
    root->rChild->lChild->lChild->lChild->data = 9;
}

//遞歸求解二叉樹的深度
int BTreeDepth(BTree *root)
{
    if (root == NULL)
        return 0;

    int left = 1 + BTreeDepth(root->lChild);
    int right = 1 + BTreeDepth(root->rChild);

    return left>right?left:right;
}

struct StackBTree
{
    BTree *bTree;
    int lFlag;//標記左孩子是否被訪問過,0:未訪問 1:已訪問
    int rFlag;;//標記右孩子是否被訪問

    StackBTree():lFlag(0),rFlag(0),bTree(NULL){};
};

//非遞歸求解二叉樹的深度--一基本思路按照棧的深度即爲從根節點到某一孩子節點的距離
int PostOrderDepth(BTree* root)
{
    int depth = 0;//保存最大深度

    if (root ==NULL)
        return depth;

    //二叉樹的深度即爲所用棧的最大深度
    stack<StackBTree> s;
    StackBTree stackBTree;
    stackBTree.bTree = root;

    s.push(stackBTree);//根節點入棧

    //每次入棧時,得到最大棧深度
    depth = (depth>s.size()?depth:s.size());

    StackBTree* topBTree = NULL;
    while (s.size()>0)
    {
        //取棧頂元素
        topBTree = &(s.top());
        if (topBTree->bTree->lChild!=NULL && topBTree->lFlag==0)
        {
            StackBTree tmpBTree;
            tmpBTree.bTree = topBTree->bTree->lChild;
            topBTree->lFlag = 1;//標記根節點左孩子已訪問
            s.push(tmpBTree);
        }
        else if ((topBTree->lFlag==1 || topBTree->bTree->lChild==NULL) && topBTree->bTree->rChild!=NULL && topBTree->rFlag==0)
        {
            //左孩子爲空或者已經訪問 && 右孩子不爲空 && 該節點右孩子未被訪問
            StackBTree tmpBTree;
            tmpBTree.bTree = topBTree->bTree->rChild;
            topBTree->rFlag = 1;//標記該節點右節點已訪問
            s.push(tmpBTree);
        }
        else
        {
            //每次入棧結束時,得到最大棧深度
            depth = (depth>s.size()?depth:s.size());
            s.pop();
        }
    }

    return depth;
}

#endif
// BTreeDepth.cpp : 定義控制檯應用程序的入口點。
//

#include "stdafx.h"
#include "btree.h"

int _tmain(int argc, _TCHAR* argv[])
{
    BTree root;
    InitBTree(&root);

    cout<<BTreeDepth(&root)<<endl;
    cout<<PostOrderDepth(&root)<<endl;
    return 0;
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章