求解二叉树的深度

求解二叉树的深度可以采用递归和非递归的方式。递归实现的代码很是简单、易懂。而非递归实现代码较复杂。

递归求解二叉树深度


递归的结束条件有两个: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;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值