【数据结构】【C#】028-二叉树(BT):🌱遍历的应用(输出叶节点,求树高度,输出某层节点)

public class BinTree<T>
{
    private static string output;

    private static void VisitNode(TreeNode<T> node)
    {
        output += node.Data.ToString() + " ";
    }

    public static void DisPlayOutPut()//显示遍历结果
    {
        Debug.Log(output);
        output = string.Empty;
    }

一、输出树的叶子节点

1、非递归:

在利用先序遍历(非递归)方法,访问节点之前,判断是否该节点左右孩子都空

if ( node.Left == null && node.Right == null )

    /// <summary>
    /// 输出树的叶子结点:非递归---利用先序非递归实现
    /// </summary>
    /// <param name="rootNode"></param>
    public static void PreOderPrintLeaves(TreeNode<T> rootNode)
    {
        TreeNode<T> node = rootNode;

        LinkStack<TreeNode<T>> S = new LinkStack<TreeNode<T>>();//使用了自己定义的链栈
        
        while (node != null || !S.IsEmpty())
        {
            while (node != null)
            {
                if (node.Left == null && node.Right == null)//判断是否是叶节点
                {
                    VisitNode(node); //访问该节点
                }
                S.Push(node);
                node = node.Left;
            }
            if (!S.IsEmpty())
            {
                node = S.Pop();
                node = node.Right;
            }
        }
        
    }

2、递归式:

与先序递归遍历类似,同样的加一个判断即可:if ( BT.Left == null && BT.Right == null )
     /// <summary>
    /// 输出树的叶子结点:递归式
    /// </summary>
    /// <param name="rootNode"></param>
    public static void PrintLeaves(TreeNode<T> rootNode)
    {
        TreeNode<T> BT = rootNode;
        if (BT != null)
        {
            if (BT.Left == null && BT.Right == null)
            {
                VisitNode(BT); //访问该节点
            }
            PrintLeaves(BT.Left);
            PrintLeaves(BT.Right);
        }
    
    }

二、输出树的高度

1、非递归:

利用层次遍历的非递归,增加 deepth变量,记录下遍历的层次,最后的层次即树的高度
    /// <summary>
    /// 输出树的高度:非递归---利用层序非递归实现
    /// </summary>
    /// <param name="rootNode"></param>
    /// <returns></returns>
    public static int LayerOderBinTreeHigh(TreeNode<T> rootNode)
    {
        if (rootNode == null) return 0;

        int deepth = 0; //记录遍历层次

        LinkQueue<TreeNode<T>> queue= new LinkQueue<TreeNode<T>>();   //创建队列,使用自定义的链队列

        TreeNode<T> outNode;      

        queue.Enqueue(rootNode);


        while (!queue.IsEmpty())
        {
            ++deepth;//当前遍历的层次

            int levelNodesCount = queue.Count;

            for (int i = 0; i < levelNodesCount; ++i)
            {
                outNode = queue.Dequeue();

                if (outNode.Left != null) queue.Enqueue(outNode.Left);
                if (outNode.Right != null) queue.Enqueue(outNode.Right);
            }

        }

        return deepth; //最终的层次:树的高度
    }

2、递归式:

利用公式 max(LH,RH)+1: 即左右子树的最大的加1 为树高度

    /// <summary>
    /// 输出树的高度:递归式---利用公式:max(LH,RH)+1
    /// </summary>
    /// <param name="rootNode"></param>
    /// <returns></returns>
    public static int BinTreeHigh(TreeNode<T> rootNode)
    {
        int LH, RH;
        TreeNode<T> BT = rootNode;
        if (BT == null)
        {
            return 0;
        }
        else
        {
            LH = BinTreeHigh(BT.Left);
            RH = BinTreeHigh(BT.Right);
            return LH > RH ? LH + 1 : RH + 1;
        }
    }

三、输出某层的所有节点(也可以输出多个层的)

1、非递归:

利用层序遍历的非递归,在访问时,判断是否 deepth==level
(输出多层,即 minLevel<=deepth<=maxLevel)
/// <summary>
    /// 输出某层的所有节点(层序遍历:非递归)
    /// </summary>
    /// <param name="rootNode"></param>
    /// <param name="level"></param>
    public static void LayerOderPrintLevelNodes(TreeNode<T> rootNode, int level)
    {
       if (rootNode == null) return;

        int deepth = 0;//记录遍历层次

        LinkQueue<TreeNode<T>> queue = new LinkQueue<TreeNode<T>>();   //创建队列,使用自定义的链队列

        TreeNode<T> outNode;

        queue.Enqueue(rootNode);

        while (!queue.IsEmpty())
        {
            ++deepth;

            int levelNodesCount = queue.Count;

            for (int i = 0; i < levelNodesCount; ++i)
            {
                outNode = queue.Dequeue();

                if (deepth == level) //判断是否是要访问的层的节点
                {
                    VisitNode(outNode);//访问节点
                }

                if (outNode.Left != null) queue.Enqueue(outNode.Left);
                if (outNode.Right != null) queue.Enqueue(outNode.Right);
            }

        }
        
    }

2、递归式:

通过判断 level==1,来确定是否到达要访问的层的节点
/// <summary>
    /// 输出某层的所有节点(递归式)
    /// </summary>
    /// <param name="rootNode"></param>
    /// <param name="level"></param>
    public static void PrintLevelNodes(TreeNode<T> rootNode, int level)
    {
        if (rootNode == null) return;
        TreeNode<T> BT = rootNode;
        if (level == 1)
        {
            VisitNode(BT);
        }
        else
        {
            PrintLevelNodes(BT.Left, level - 1);
            PrintLevelNodes(BT.Right, level - 1);
        }
    }

测试用例:

public class _017_BinTree : MonoBehaviour
{
    //二叉树结构: 
    private string tree = @"     
              1
             / \
            2   3
           / \
          4   5
         / \ 
        6   7              
                           ";

    TreeNode<int> root; //二叉树根节点

    //创建二叉树
    void CreatBinTree()
    {
       
        root = new TreeNode<int>(1);
        TreeNode<int> t2 = new TreeNode<int>(2);
        TreeNode<int> t3 = new TreeNode<int>(3);
        TreeNode<int> t4 = new TreeNode<int>(4);
        TreeNode<int> t5 = new TreeNode<int>(5);
        TreeNode<int> t6 = new TreeNode<int>(6);
        TreeNode<int> t7 = new TreeNode<int>(7);

        root.SetLRChild(t2, t3);
        t2.SetLRChild(t4, t5);
        t4.SetLRChild(t6, t7);
    }

    void Start()
    {
        CreatBinTree();//创建二叉树

        
        Debug.Log("二叉树结构:" + "\n" + tree);

       
        //遍历应用:
        Debug.Log("输出树的叶子节点:");
        Debug.Log("---------非递归----利用先序非递归实现-----");
        BinTree<int>.PreOderPrintLeaves(root);
        BinTree<int>.DisPlayOutPut();

        Debug.Log("---------递归式----利用先序递归实现-------");
        BinTree<int>.PrintLeaves(root);
        BinTree<int>.DisPlayOutPut();

        Debug.Log("输出树的高度:");
        Debug.Log("---------非递归----利用层序非递归实现------");
        int high1= BinTree<int>.LayerOderBinTreeHigh(root);
        Debug.Log("树的高度: " + high1);        

        Debug.Log("---------递归式----利用公式:max(LH,RH)+1 ");
        int high2 = BinTree<int>.BinTreeHigh(root);
        Debug.Log("树的高度: " + high2);

        Debug.Log("输出第4层的所有节点:");
        Debug.Log("---------非递归----判断 deepth==level-----");
        BinTree<int>.LayerOderPrintLevelNodes(root,4);
        BinTree<int>.DisPlayOutPut();

        Debug.Log("---------递归式----判断 Leve==1-----------");
        BinTree<int>.PrintLevelNodes(root, 4);
        BinTree<int>.DisPlayOutPut();

    }
}

测试结果:


其他应用:

四、 二元运算表达式树及其遍历

1、先序遍历得到前缀表达式:+ + a * b c * + * d e f g
2、中序遍历得到中缀表达式:a + b * c +d * e + f * g(中缀表达式会受到运算符优先级的影响 :需要在遍历时加括号
3、后序遍历得到后缀表达式:a b c * + d e * f + g * +

五、两种遍历序列确定二叉树

已知三种遍历中的任意两种遍历序列, 能否唯一确定一棵二叉树呢?

答案:必须要有中序遍历才行

例子:先序和中序遍历序列来确定一棵二叉树
  • 根据先序遍历序列第一个结点确定根结点
  • 根据根结点中序遍历序列中分割出左右两个子序列
  • 左子树和右子树分别递归使用相同的方法继续分解
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,793评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 87,567评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,342评论 0 338
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,825评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,814评论 5 368
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,680评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,033评论 3 399
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,687评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 42,175评论 1 300
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,668评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,775评论 1 332
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,419评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,020评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,978评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,206评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,092评论 2 351
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,510评论 2 343

推荐阅读更多精彩内容

  • 目录 1、什么是树 2、相关术语 3、二叉树 3.1、二叉树的类型 3.2、二叉树的性质 3.3、二叉树的结构 3...
    我哈啊哈啊哈阅读 2,536评论 0 10
  • 一些概念 数据结构就是研究数据的逻辑结构和物理结构以及它们之间相互关系,并对这种结构定义相应的运算,而且确保经过这...
    Winterfell_Z阅读 5,654评论 0 13
  • 数据结构和算法--二叉树的实现 几种二叉树 1、二叉树 和普通的树相比,二叉树有如下特点: 每个结点最多只有两棵子...
    sunhaiyu阅读 6,422评论 0 14
  • 有时候还是挺羡慕姬友那“老子就是毒且独”的担当的,她的比喻也十分有趣:我身在粪坑,我心心念念千里之外的游泳池。毕竟...
    逢凶化吉满天杀阅读 919评论 0 1
  • 在梦中死去 在清晨醒来 死过一次的人 好好珍惜生命
    漫语和流年阅读 173评论 0 2