从上到下打印二叉树

问题一:从上到下打印二叉树

从上往下打印出二叉树的每个节点,同层节点从左至右打印。

看到这个问题,第一脑海里就浮现出了数据结构期间学到的树的广度遍历,那么按照当时的思路,就是建立一个队列(因为队列有先进先出的性质),从第一个根节点开始,把根节点储存进队列中,然后判断队列是否为空,不为空则打印该节点,然后判断该节点的左右子树是否为空,不为空,把它的左右子树添加进队列中,以此类推,直到最后把所有不为空的节点全部输出,结束循环。
思路出来之后,那么我们可以假设树的结构如下:
这里写图片描述
题外话:作为一名灵魂画手,时不时的就得展露自己的高超手艺来吸引浏览量(我不会坦言是我网速差到打不开制图软件才用画板画的[手动捂脸])。

那么对于从上到下打印可有以下过程:
这里写图片描述

知道解决方法之后,那么就通过代码实现并测试吧!
有两个测试:
1、二叉树不为空,输出正确的顺序
2、二叉树为空,返回一个空集合

以下为参考代码:

using System;
using System.Collections.Generic;
using System.Linq;

namespace 从上到下打印二叉树
{
    public class TreeNode
    {
        public int val;
        public TreeNode left;
        public TreeNode right;
        public TreeNode(int x)
        {
            val = x;
        }
    }

    class Program
    {
        static void Main(string[] args)
        {
            TreeNode tree = CreateTree(null);
            Solution s = new Solution();
            List<int> list = s.PrintFromTopToBottom(tree);
            s.PrintList(list);
            list = s.PrintFromTopToBottom(null);
            s.PrintList(list);
        }

        private static TreeNode CreateTree(TreeNode root)
        {
            if (root == null)
            {

                TreeNode tree = new TreeNode(1)
                {
                    left = new TreeNode(2),
                    right = new TreeNode(3)
                };
                tree.left.left = new TreeNode(4);
                tree.left.right = new TreeNode(5);
                tree.right.left = new TreeNode(6);
                tree.right.right = new TreeNode(7);

                return tree;
            }
            else
                return root;
        }
    }

    class Solution
    {
        public List<int> PrintFromTopToBottom(TreeNode root)
        {
            List<int> list = new List<int>();
            Queue<TreeNode> queue = new Queue<TreeNode>();

            if (root == null)
                return list;

            queue.Enqueue(root);

            while (queue.Count() != 0)
            {
                TreeNode pNode = queue.Dequeue();
                list.Add(pNode.val);
                if (pNode.left != null)
                    queue.Enqueue(pNode.left);
                if (pNode.right != null)
                    queue.Enqueue(pNode.right);
            }

            return list;
        }

        public void PrintList(List<int> list)
        {
            if(list==null||list.Count<=0)
            {
                Console.WriteLine("null");
                return;
            }
            foreach (int item in list)
                Console.Write(item + "\t");

            Console.WriteLine();
        }
    }
}

题目二:怎样分行从上到下打印二叉树

从上到下分层打印二叉树,同一层的节点按从左到右的顺序打印,每一层打印一行。例如打印如下二叉树
这里写图片描述
得出的结果应该是:
8
7 6
3 2 1 4

此题和上述题目一类似,也可以用一个队列来保存,但是为了保证把每一行单独的打印到一行里,需要设置两个变量,一个变量表示当前层中是否还有节点数没有被打印,另一个变量是下一层的节点数目。

以下为打印方法的参考代码:

public void PrintFromTopToBottomByLayer(TreeNode root)
{
    Queue<TreeNode> queue = new Queue<TreeNode>();

    if (root == null)
        return;

    //nextLayer 表示下一层需要打印的元素个数,toBePrint表示当前层需要打印的元素个数
    int nextLayer = 0, toBePrint = 1;

    queue.Enqueue(root);
    while (queue.Count > 0)
    {
        TreeNode pNode = queue.Dequeue();
        if(pNode.left!=null)
        {
            nextLayer++;
            queue.Enqueue(pNode.left);
        }
        if (pNode.right != null)
        {
            nextLayer++;
            queue.Enqueue(pNode.right);
        }

        Console.Write(pNode.val + "\t");
        toBePrint--;
        if (toBePrint == 0)
        {
            toBePrint = nextLayer;
            nextLayer = 0;
            Console.WriteLine();
        }
    }
}

问题三:之字形打印二叉树

问题描述
请实现一个函数按照之字形顺序打印二叉树,及第一行按照从左到右的顺序打印,第二层按照从右到左的顺序打印,第三行再按照从左到右的顺序打印,以此类推。
例如,按照之字形顺序打印下图二叉树
这里写图片描述
结果应该为:
1
3 2
4 5 6 7
15 14 13 12 11 10 9 8

我们以上面的二叉树为例来分析过程:
当根节点1打印之后,它的左子节点和右子节点先后保存到了一个数据容器中。打印第二层时,先打印3,再打印2。可以发现这个节点的打印是先进后出的,因此数据容器可以用栈来实现。
接着打印第二层你的两个节点。根据之字形顺序,先打印3节点,再打印2节点,并把它们的子节点保存到一个数据容器里。打印第三层时,会先打印节点2的两个子节点,再打印节点3的两个子节点。这意味着我们需要再定义一个栈来保存节点2和节点3的子节点。
分析到这里,可以得出的规律有:按之字形顺序打印二叉树需要两个栈,打印某一层时,把下一层的节点保存到相应的栈里。如果当前是奇数层(第一层,第三层),那么先保存左子节点再保存右子节点到第一个栈里;如果当前是偶数层(第二层),则先保存右子节点再保存左子节点到第二个栈里。
为什么要用两个栈?我们可以看看第二层到第三层的打印,如果打印节点时,先后把节点2和节点3压入栈里。接下来打印节点3,打印节点3时需要把它的左右子节点压入栈里,此时由于它的右子节点为7,就会导致下一个打印的节点为7,而不是节点2。所以为了避免这个问题,我们需要定义两个栈。

按之字形顺序打印二叉树,以下为打印过程:
这里写图片描述

以下为上述功能的方法实现代码:

public void PrintFromTopToBottomByLayerOfZ(TreeNode root)
{
    if (root == null)
    {
        Console.WriteLine("null");
        return;
    }
    //定义两个栈,一个储存当前层的元素,另一个储存下一层的元素
    Stack<TreeNode>[] level = { new Stack<TreeNode>(), new Stack<TreeNode>() };
    //表示当前层的栈下标和下一层的栈下标
    int current = 0;
    int next = 1;
    //首先把根节点压入当前层的栈中
    level[current].Push(root);
    //如果当前层的栈和下一层的栈有一个栈不为空,则打印
    while (level[current].Count > 0 || level[next].Count > 0)
    {
        //取出栈顶元素
        TreeNode pNode = level[current].Pop();
        //打印
        Console.Write(pNode.val + "\t");
        //如果当前层是奇数层,则从左到右压入子树数据
        if (current == 0)
        {
            if (pNode.left != null)
                level[next].Push(pNode.left);
            if (pNode.right != null)
                level[next].Push(pNode.right);
        }
        //如果当前层是偶数层,则从右到左压入子树数据
        else
        {
            if (pNode.right != null)
                level[next].Push(pNode.right);
            if (pNode.left != null)
                level[next].Push(pNode.left);
        }
        //如果当前层的所有数据全部弹出,则换一行进行下一层的打印
        if (level[current].Count == 0)
        {
            Console.WriteLine();
            current = 1 - current;
            next = 1 - next;
        }
    }
}
  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值