求解二叉樹的深度可以採用遞歸和非遞歸的方式。遞歸實現的代碼很是簡單、易懂。而非遞歸實現代碼較複雜。
遞歸求解二叉樹深度
遞歸的結束條件有兩個: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;
}