二叉树梳理

本文详细介绍了二叉树的非递归遍历方法,包括前序遍历、中序遍历,并探讨了二叉树的深度计算及叶子节点计数等问题。通过具体的代码实例,帮助读者更好地理解和掌握二叉树的遍历技巧。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

本篇文章主要涉及到
  • 二叉树的非递归遍历(ForwardTravesal()/MiddleTravesal()
  • 二叉树的深度: DepthOfTree()
  • 二叉树的叶子节点个数: CountsOfLeaves()

二叉树的非递归需要借助,原因在于递归遍历思想是基于的,现在要变为非递归,需要借助额外空间,空间换时间。

  • 前序遍历ForwardTravesal()—–根左右
    1.当前节点p,访问p->data将p存入Stack
    2.若p->left存在,将p->left作为当前的p;若不存在,将栈顶元素出栈,再将p->right作为当前的p
    3.栈空即为结束
void NonRecursiveForward(BiTree root)
{
    BiTree p = root;
    int depth = DepthOfTree(root);
    BiTree *stack = (BiTree *)malloc(sizeof(BiTree)*depth);
    int top = -1;

    while(p != NULL || top != -1)
    {
        while(p != NULL)
        {
            cout<<p->data<<" ";
            stack[++top] = p;
            p = p->left;
        }

        if(top != -1)
        {
            p = stack[top--];
            p = p->right;
        }
    }
    cout<<endl;
}

  • 中序遍历MiddleTravesal()—–左根右
    注:中序遍历与前序遍历输出时机不同,相信大家秒懂。
void NonRecursiveMiddle(BiTree root)
{
    BiTree p = root;
    int depth = DepthOfTree(root);
    BiTree *stack = (BiTree *)malloc(sizeof(BiTree)*depth);
    int top = -1;

    while(p != NULL || top != -1)
    {
        while(p != NULL)
        {
            stack[++top] = p;
            p = p->left;
        }

        if(top != -1)
        {
            p = stack[top--];
            cout<<p->data<<" ";
            p = p->right;
        }
    }
    cout<<endl;
}
二叉树的深度,可以采用递归来解决,通俗易懂。

树的深度等于当前节点深度 = 1 + 子树(左子树和右子树最大深度)深度

/**
* get depth of tree
*/
int DepthOfTree(BiTree root)
{
    int deep = 0;
    if (root)
    {
        int leftDepth = DepthOfTree(root->left);
        int rightDepth = DepthOfTree(root->right);
        deep = leftDepth >= rightDepth ? leftDepth+1 : rightDepth+1;
    }
    return deep;
}
二叉树叶子节点个数等价于

满足left == NULL && right == NULL的节点
同理,知道叶子节点个数就会知道度为2的节点个数

/**
* get counts of leaves
*/
int CountsOfLeaves(BiTree root)
{
    //int count = 0;

    if (!root)
        return 0;

    if (root->left == NULL && root->right == NULL)
    {
        return 1;
    }

    int lc = CountsOfLeaves(root->left);
    int rc = CountsOfLeaves(root->right);
    return (lc+rc);
}
二叉树按层遍历TravesalByLayer(),同样需要借助额外空间
利用队列先进先出的特性,可以实现,爱思考的大家动手吧。

心得

经过一个多月的面试,遇到算法题中二叉树相关的比较多,比如左右子树相交的第一个节点,堆排序的树结构链表实现等。总的来说,树说难不难,说易不易,理解其中的编程思想很重要。


完整代码

#include <iostream>
using namespace std;

typedef int DataType;

typedef struct node
{
    DataType data;
    struct node *left;
    struct node *right;
}BTNode, *BiTree;


int CreateABinaryTree(BiTree *t)
{
    // static count = 0;
    *t = (BiTree)malloc(sizeof(BTNode));
    if (!(*t))
    {
        /* can't create tree */
        exit(-1);
    }

    DataType dt;
    cin>>dt;
    if (dt == -1)
    {
        /* code */
        *t = NULL;
    }else
    {
        (*t)->data = dt;
        cout<<"You can input data to left (Root is "<<dt<<"): "<<endl;
        CreateABinaryTree(&((*t)->left));
        cout<<"You can input data to right (Root is "<<dt<<"): "<<endl;
        CreateABinaryTree(&((*t)->right));
    }

    return 1;
}

/**
*
* Traversal with Recursive to BTree
*
*/

void RecursiveRootLeftRight(BiTree root)
{
    if (root)
    {
        /* code */
        cout<<root->data<<" ";
        RecursiveRootLeftRight(root->left);
        RecursiveRootLeftRight(root->right);
    }
}



void RecursiveLeftRootRight(BiTree root)
{
    if (root)
    {
        /* code */
        RecursiveLeftRootRight(root->left);
        cout<<root->data<<" ";
        RecursiveLeftRootRight(root->right);
    }
}

void RecursiveLeftRightRoot(BiTree root)
{
    if (root)
    {
        /* code */
        RecursiveLeftRightRoot(root->left);
        RecursiveLeftRightRoot(root->right);
        cout<<root->data<<" ";
    }
}

/**
* get depth of tree
*/
int DepthOfTree(BiTree root)
{
    int deep = 0;
    if (root)
    {
        int leftDepth = DepthOfTree(root->left);
        int rightDepth = DepthOfTree(root->right);
        deep = leftDepth >= rightDepth ? leftDepth+1 : rightDepth+1;
    }
    return deep;
}

/**
* get counts of leaves
*/
int CountsOfLeaves(BiTree root)
{
    //int count = 0;

    if (!root)
        return 0;

    if (root->left == NULL && root->right == NULL)
    {
        return 1;
    }

    int lc = CountsOfLeaves(root->left);
    int rc = CountsOfLeaves(root->right);
    return (lc+rc);
}

/**
*
* Traversal with Non-Recursive to BTree
*
*/

void NonRecursiveForward(BiTree root)
{
    BiTree p = root;
    int depth = DepthOfTree(root);
    BiTree *stack = (BiTree *)malloc(sizeof(BiTree)*depth);
    int top = -1;

    while(p != NULL || top != -1)
    {
        while(p != NULL)
        {
            cout<<p->data<<" ";
            stack[++top] = p;
            p = p->left;
        }

        if(top != -1)
        {
            p = stack[top--];
            p = p->right;
        }
    }
    cout<<endl;
}

void NonRecursiveMiddle(BiTree root)
{
    BiTree p = root;
    int depth = DepthOfTree(root);
    BiTree *stack = (BiTree *)malloc(sizeof(BiTree)*depth);
    int top = -1;

    while(p != NULL || top != -1)
    {
        while(p != NULL)
        {
            stack[++top] = p;
            p = p->left;
        }

        if(top != -1)
        {
            p = stack[top--];
            cout<<p->data<<" ";
            p = p->right;
        }
    }
    cout<<endl;
}



int main(int argc, char const *argv[])
{
    cout<<"Datasource fo Tree "<<endl;
    BiTree root;
    /** create a binary tree */
    CreateABinaryTree(&root);
    cout<<"Binary Tree is created well."<<endl;
    cout<<"Depth Of Tree: "<<DepthOfTree(root)<<endl;
    cout<<"Counts Of Leaves: "<<CountsOfLeaves(root)<<endl;
    /** Forward Traversal */
    cout<<"*** Recursive Forward Traversal ***"<<endl;
    RecursiveRootLeftRight(root);
    cout<<endl;
    /** Middle Traversal */
    cout<<"*** Recursive Middle Traversal ***"<<endl;
    RecursiveLeftRootRight(root);
    cout<<endl;
    /** Backward Traversal */
    cout<<"*** Recursive Backward Traversal ***"<<endl;
    RecursiveLeftRightRoot(root);
    cout<<endl;
    cout<<"*** Non-Recursive Forward Traversal ***"<<endl;
    NonRecursiveForward(root);
    cout<<"*** Non-Recursive Middle Traversal ***"<<endl;
    NonRecursiveMiddle(root);
    return 0;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值