二叉树

什么是二叉树

当我们得到一个数,就将这个数放在第一位,拿到第二个数时,对比第一个数,小则放在左边(左孩子Left),大则放在右边(Right),接下来依次类推。


  • 深度优先遍历DFS:(栈)递归方法
  • 前序遍历(Pre—Order)(根左右)
  • 中序遍历(In-Order)(左根右)会让树按顺序排列
  • 后序遍历 (Post—Order)(左右根)

  • 广度优先遍历(层次遍历)队列方法

给你一个数组int[] a=new int[]{8,4,12,2,6,10,14};
经过一些排序后得到类似于这样一颗倒转过来的数型图
image

完整代码:

Tree.cs
    class Tree<T> where T:IComparable<T>
    {
        private class Node
        {
            public T Val { get; set; }
            public Node Left { get; set; }
            public Node Right { get; set; }
            public Node(T val)
            {
                this.Val=val;
                this.Left=null;
                this.Right=null;
            }
        }

        private Node root;  //我们的根节点
        private int N;   //存储元素的个数
        public Tree()   //当我们实例一个对象时候初始化
        {
            root=null;
            N=0;
        }

        public int Count { get{return N;} }
        public bool IsEmpty {get{return N==0;}}   //N为0代表没有节点

        //非递归添加元素
        public void add(T val)
        {
            if(root==null)
            {
                root=new Node(val);
                N++;
                return;
            }

            Node pre=null;
            Node cur=root;

            while(cur!=null)
            {
                if(val.CompareTo(cur.Val)==0) return;

                pre=cur;
                
                if(val.CompareTo(cur.Val)<0)
                {
                    cur=cur.Left;
                }
                else if(val.CompareTo(cur.Val)>0)
                {
                    cur=cur.Right;
                }  
            }
            cur=new Node(val);   //当cur所指向的节点为空时,创建新叶子
            if(val.CompareTo(pre.Val)<0) 
            {
                pre.Left=cur;
            }else
            {
                pre.Right=cur;
            }
            N++;  //多了一个元素
        }

        //递归方式添加新元素
        public void Add(T val)
        {
            root=Add(root,val);
        }

        private Node Add(Node Root,T val)
        {
            if(Root==null)
            {
                N++;
                return new Node(val);
            }

            if(val.CompareTo(Root.Val)<0)
            {
                Root.Left=Add(Root.Left,val);     //递归到最后会返回一个Node节点,用left去接住
            }
            if(val.CompareTo(Root.Val)>0)
            {
                Root.Right=Add(Root.Right,val);   //同理
            }

            return Root;
        }

        //查找元素
        public bool Contains(T val)
        {
            return Contains(root,val);
        }

        private bool Contains(Node Root,T val)
        {
            if(Root==null)
            {
                return false;
            }
            
            if(val.CompareTo(Root.Val)==0)
            {
                return true;
            }
            else if(val.CompareTo(Root.Val)<0)
            {
                return Contains(Root.Left,val);
            }
            else
            {
                return Contains(Root.Right,val);
            }
        }


        //前序遍历(PreOrder) 根左右
        public void PreOrder()
        {
            PreOrder(root);
        }

        private void PreOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }

            System.Console.WriteLine(Root.Val);
            PreOrder(Root.Left);
            PreOrder(Root.Right);
        }

        //中序遍历(In-Order)左根右
        public void InOrder()
        {
            InOrder(root);
        }

        private void InOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }
            InOrder(Root.Left);
            System.Console.WriteLine(Root.Val);
            InOrder(Root.Right);
        }

        //后序遍历(Post-Order)
        public void PostOrder()
        {
            PostOrder(root);
        }

        private void PostOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }

            PostOrder(Root.Left);
            PostOrder(Root.Right);
            System.Console.WriteLine(Root.Val);
        }

        //广度优先遍历(层次遍历)
        public void LevelOrder()
        {
            LevelOrder(root);
        }

        private void LevelOrder(Node Root)
        {
            Queue<Node> q=new Queue<Node>();
            q.Enqueue(root);
            while(q.Count!=0)
            {
                Node cur=q.Dequeue();
                System.Console.WriteLine(cur.Val);

                if(cur.Left!=null)
                {
                    q.Enqueue(cur.Left);
                }
                if(cur.Right!=null)
                {
                    q.Enqueue(cur.Right);
                }

            }

        }

        //查找最小值
        public T Min()
        {
            if(root==null)
            {
                throw new ArgumentException("空树");
            }
            return Min(root).Val;
        }

        private Node Min(Node Root)
        {
            if(Root.Left==null)
            {
                return Root;
            }

            return Min(Root.Left);
        }

        //查找最大值
        public T Max()
        {
            if(root==null)
            {
                throw new ArgumentException("空树");
            }
            return Max(root).Val;

        }

        private Node Max(Node Root)
        {
            if(Root.Right==null)
            {
                return Root;
            }
            
            return Max(Root.Right);
        }

        //删除最小值,最大值
        public T RemoveMin()
        {
            T val=Min();
            RemoveMin(root);
            return val;
        }

        private Node RemoveMin(Node Root)
        {
            if(Root.Left==null)
            {
                N--;
                return Root.Right;
            }

            Root.Left=RemoveMin(Root.Left);
            return Root;
        }

        public T RemoveMax()
        {
            T val=Max();
            RemoveMax(root);
            return val;
        }

        private Node RemoveMax(Node Root)
        {
            if(Root.Right==null)
            {
                N--;
                return Root.Left;
            }

            Root.Right=RemoveMax(Root.Right);
            return Root;
        }

        //删除任意节点
        public void Remove(T e)
        {
            root=Remove(root,e);
        }

        private Node Remove(Node Root,T e)
        {
            if(Root==null) return null;
            if(e.CompareTo(Root.Val)<0)
            {
                Root.Left=Remove(Root.Left,e);
                return Root;
            }
            else if(e.CompareTo(Root.Val)>0)
            {
                Root.Right=Remove(Root.Right,e);
                return Root;
            }
            else
            {
                if(Root.Left==null)
                {
                    N--;
                    return Root.Right;
                }
                if(Root.Right==null)
                {
                    N--;
                    return Root.Left;
                }
                Node s=Min(Root.Right);
                s.Right=RemoveMin(Root.Right);
                s.Left=Root.Left;
                return s;
            }
        }

        //树的高度取值
        public int MaxHeight()
        {
            return MaxHeight(root);
        }

        private int MaxHeight(Node Root)
        {
            if(Root==null) return 0;
            int l=MaxHeight(Root.Left);
            int r=MaxHeight(Root.Right);
            return Math.Max(l,r)+1;
        }
    }
Program.cs
    class Test
    {
    static void Main(string[] arg)
    {
        int[] a=new int[]{8,4,12,2,6,10,14};
        Tree<int> tree=new Tree<int>();
        for(int i=0;i<a.Length;i++)
        {
            tree.Add(a[i]);
        }

        int maxH=tree.MaxHeight();
        System.Console.WriteLine(maxH);
        // tree.PreOrder(); //前序深度优先遍历
        // System.Console.WriteLine("=========");
        // tree.InOrder(); //中序深度优先遍历
        // System.Console.WriteLine("=========");
        // tree.PostOrder(); //后序深度优先遍历
        // System.Console.WriteLine("=========");
        // tree.LevelOrder(); //广度优先遍历
        // System.Console.WriteLine("=========");
        // System.Console.WriteLine(tree.Min());
        // System.Console.WriteLine("=========");
        // System.Console.WriteLine(tree.Max());
        // System.Console.WriteLine(tree.Count);
        //System.Console.WriteLine("删除了最小值{0}",tree.RemoveMin());
        // System.Console.WriteLine("删除了最大值{0}",tree.RemoveMax());
        // System.Console.WriteLine(tree.Count);
        // tree.Remove(12);
        // tree.InOrder(); //中序深度优先遍历 
    }

    }

如何添加新元素

非递归的方法:
首先创建一个cur指针与pre指针,pre是跟在cur后面的,当有一个数字进来时候,如果还是空树,则初始化root,不是则对root进行比较,小则在Left,大则在Left,先让pre等于cur,再让cur去移动,当移动到一个null值时候,退出循环,cur此时new个新节点,cur的值与pre比较,小则将pre的左孩子=cur,大则将pre的右孩子=cur
递归:
当传进来的根为null值时,则创建新值并初始化,如果有根,则再衍生,通过递归对比数字,达到合适的位置返回一个Node节点,完成添加。

前序深度优先遍历

先打印根的值,在递归左孩子,再递归右孩子

点击查看代码
        private void PreOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }

            System.Console.WriteLine(Root.Val);
            PreOrder(Root.Left);
            PreOrder(Root.Right);
        }

中序深度优先遍历

先递归左孩子,然后递归到左孩子为null时候,返回到打印当前根的值,再进入右孩子递归,适合来做二叉树的顺序查找

点击查看代码
        private void InOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }
            InOrder(Root.Left);
            System.Console.WriteLine(Root.Val);
            InOrder(Root.Right);
        }

后序深度优先遍历

先递归左孩子,再右孩子,最后打印值根的值

点击查看代码
        private void PostOrder(Node Root)
        {
            if(Root==null)
            {
                return;
            }

            PostOrder(Root.Left);
            PostOrder(Root.Right);
            System.Console.WriteLine(Root.Val);
        }

广度优先遍历

利用队列,不用递归,也就不增加函数调用栈,是一种层级遍历,对于树的高度太庞大时使用,主要思想就是加二打一
首先把根加进队列,写个循环,当队列的值不为空时,将值拿出,打印,之后加入左孩子与右孩子进队列,以此循环,直到队列没有节点

点击查看代码
        private void LevelOrder(Node Root)
        {
            Queue<Node> q=new Queue<Node>();
            q.Enqueue(root);
            while(q.Count!=0)
            {
                Node cur=q.Dequeue();
                System.Console.WriteLine(cur.Val);

                if(cur.Left!=null)
                {
                    q.Enqueue(cur.Left);
                }
                if(cur.Right!=null)
                {
                    q.Enqueue(cur.Right);
                }

            }

        }
posted @ 2022-02-10 23:26  Ariaaaaa  阅读(7)  评论(0)    收藏  举报