C# 递归实现二叉树先序创建、遍历、对称二叉树判断

二叉链表存储结构

使用二叉链表存储二叉树,声明结点类:

    public class Node<T>
    {
        //声明字段:数据域、左孩子、右孩子;
        public T data;
        public Node<T> lChild;
        public Node<T> rChild;

        //声明属性:
        public T Data { get => data; set => data = value; }
        public Node<T> LChild { get => lChild; set => lChild = value; }
        public Node<T> RChild { get => rChild; set => rChild = value; }

        //重载构造函数:
        public Node(T data)
        {
            this.data = data;
        }

        public Node(T data, Node<T> lChild, Node<T> rChild)
        {
            this.data = data;
            this.lChild = lChild;
            this.rChild = rChild;
        }

        public Node()
        {
            this.data = default;
            this.lChild = null;
            this.rChild = null;
        }
    }

声明二叉树类,同时声明层次遍历方法,在LinkBiTree类中,我使用了preOrderList、midOrderList以及postOrderList三个列表类型字段来存储遍历得到的结果。

    //声明类:二叉树
    public class LinkBiTree<T>
    {
        //声明字段:根节点;
        public Node<T> head;

        //声明属性:
        public Node<T> Head { get { return head; } set { head = value; } }

        //重载构造函数:
        public LinkBiTree(T data)
        {
            Node<T> p = new Node<T>(data);
            head = p;
        }

        public LinkBiTree()
        {
            head = null;
        }

        //声明方法:判断是否为空
        public bool IsEmpty()
        {
            return head == null;
        }

        //声明字段:用于存储遍历列表
        public List<T> preOrderList = new List<T>();
        public List<T> midOrderList = new List<T>();
        public List<T> postOrderList = new List<T>();
    }

递归算法实现二叉树遍历

先根遍历

先根遍历的原理就是先访问根结点,然后分别先序遍历左子树、右子树。即对于每一个结点来说,都需要不断往下搜索,直到搜索到null空结点为止。在搜索过程中的每一个结点都遵循根、左、右的遍历顺序,代码实现如下:

        //LinkBiTree 
        public void PreOrder(Node<T> root)
        {
            if (IsEmpty())
            {
                Console.WriteLine("Tree is empty!!");
            }

            if (root != null)
            {
                preOrderList.Add(root.data);//将结果保存在列表中;
                PreOrder(root.LChild);
                PreOrder(root.rChild);
            }
        }
       

中根遍历

同理,可以通过左、根、右的顺序实现中根遍历的递归算法。代码实现如下:

        //LinkBiTree
        //声明方法:使用递归进行中序遍历
        public void MidOrder(Node<T> root)
        {
            if (IsEmpty())
            {
                Console.WriteLine("Tree is empty!!");
            }

            if (root != null)
            {
                //在这里体现左、根、右的遍历顺序:
                MidOrder(root.LChild);
                midOrderList.Add(root.data);//将结果保存在列表中;
                MidOrder(root.rChild);
            }
        }

 后根遍历

        //LinkBiTree
        //声明方法:使用递归进行后序遍历
        public void PostOrder(Node<T> root)
        {
            if (IsEmpty())
            {
                Console.WriteLine("Tree is empty!!");
            }

            if (root != null)
            {
                //在这里体现根、左、右的遍历顺序:
                PostOrder(root.LChild);
                PostOrder(root.rChild);
                postOrderList.Add(root.data);//将结果保存在列表中;
            }
        }

先序建立二叉树

建立二叉树可以通过先序、中序、后序遍历得到的序列进行还原,但前提是所有的叶子必须是#,即表示该处为空结点。建立二叉树的过程同样通过递归实现,输入形参root作为该二叉树的根节点,建立二叉链表。
在该方法中,我使用队列preQueue存储输入的遍历序列,每次DeQueue()得到数据字段temp,建立起左子树、右子树,并实现递归,以temp.equals(“#”)作为出口。(中序、后序的原理与此相同)代码演示如下:

        //LinkBiTree
        //声明方法:先序建立二叉树
        public void PreCreateTree(ref Node<T> root)
        {
            T temp = preQueue.Dequeue();


            if (temp.Equals("#"))
            {
                root = null;
            }
            else
            {
                root = new Node<T>(temp);
                PreCreateTree(ref root.lChild);
                PreCreateTree(ref root.rChild);
            }

            return;
        }

判断二叉树是否为对称二叉树

对称二叉树的判断,可以基于左右子树的深度进行判断。所以我声明了TreeDepth()方法,能够从root出发,通过想左子树和右子树分别遍历,得到各个结点的最大深度,即为该树的深度。在此基础上,我使用IsBalanceTree()方法判断二叉树是否为对称二叉树。在当中我使用了字段dis,用于存储该节点左右子树的深度之差,如果为0,则进一步判断,实现递归。

        //LinkBiTree
        //声明方法:求树的深度
        public int TreeDepth(Node<T> root)
        {
            if (root == null)
            {
                return 0;
            }

            else
            {
                int left_depth = TreeDepth(root.LChild);
                int right_depth = TreeDepth(root.rChild);

                if (left_depth > right_depth)
                {
                    return left_depth + 1;
                }
                else
                {
                    return right_depth + 1;
                }
            }
        }

        //重载方法:
        public int TreeDepth()
        {
            return TreeDepth(head);
        }

        public Queue<T> preQueue = new Queue<T>();

        //声明方法:判断一棵树是否是对称二叉树:
        public bool IsBalanceTree(Node<T> root)
        {
            if (root == null)
            {
                return true;
            }

            //创建字段dis,存储左右子树的深度差:
            int dis = TreeDepth(root.lChild) - TreeDepth(root.rChild);

            //进入判断,递归运算:
            if (dis != 0)
            {
                return false;
            }
            else
            {
                return IsBalanceTree(root.rChild) && IsBalanceTree(root.lChild);
            }
        }

        //重载方法:
        public bool IsBalanceTree()
        {
            return IsBalanceTree(head);
        }

本文的方法均遵循递归的思路实现,这也是基于二叉链表这一存储方式和二叉树这一结构的特殊性。欢迎批评指正,有任何问题都可以私信我!

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 6
    评论
评论 6
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Taylor乐乐子

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值