美文网首页
树的遍历总结

树的遍历总结

作者: 零_53f4 | 来源:发表于2019-07-22 19:43 被阅读0次

    写在前面

    本文是根据2篇参考文献整合的,后续有关于树的更好的思路会持续更新

    树的定义

    // lombok 标签 @Data
    @Data
    public class TreeNode<T>
    { 
        public T Data;
        public TreeNode<T> LChild;     
        public TreeNode<T> RChild;
    }
    

    前序遍历

    前序递归

    public static void PreOrderRecur(TreeNode<char> treeNode)
     {
         if (treeNode == null)
         {
             return;
         }
         Console.Write(treeNode.Data); 
         PreOrderRecur(treeNode.LChild);
         PreOrderRecur(treeNode.RChild);
     }
    

    前序非递归

     public static void PreOrder(TreeNode<char> head)
    {
        if (head == null)
        {
            return;
        }
        Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
        stack.Push(head);
        while (!(stack.Count == 0))
        {
            TreeNode<char> cur = stack.Pop();
            Console.Write(cur.Data);
    
            if (cur.RChild != null)
            {
                stack.Push(cur.RChild);
            }
            if (cur.LChild != null)
            {
                stack.Push(cur.LChild);
            }
        }
    }
    

    中序遍历

    中序递归

    public static void InOrderRecur(TreeNode<char> treeNode)
    {
        if (treeNode == null)
        {
            return;
        }  
        InOrderRecur(treeNode.LChild);
        Console.Write(treeNode.Data); 
        InOrderRecur(treeNode.RChild);
    }
    

    中序非递归

    public static void InOrder(TreeNode<char> treeNode)
    {
        if (treeNode == null)
        {
            return;
        }
        Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
    
        TreeNode<char> cur = treeNode;
    
        while (!(stack.Count == 0) || cur != null)
        {
            while (cur != null)
            {
                stack.Push(cur);
                cur = cur.LChild;
            }
            TreeNode<char> node = stack.Pop();
            Console.WriteLine(node.Data);
            cur = node.RChild;
        }
    }
    

    后序遍历

    后序递归

    public static void PosOrderRecur(TreeNode<char> treeNode)
    {
        if (treeNode == null)
        {
            return;
        }
        PosOrderRecur(treeNode.LChild);
        PosOrderRecur(treeNode.RChild);
        Console.Write(treeNode.Data); 
    }
    

    后序非递归

    双栈法

    class Solution {
        public List<Integer> postorderTraversal(TreeNode root) {
             List<Integer> result = new LinkedList<>();
             if (root == null) return result;
     
             Stack<TreeNode> toVisit = new Stack<>();
             Stack<TreeNode> reversedStack = new Stack<>();
             toVisit.push(root);
             TreeNode cur;
     
             while (!toVisit.isEmpty()) {
                 cur = toVisit.pop();
                  reversedStack.push(cur);  // result.add(cur.val);
                 if (cur.left != null) toVisit.push(cur.left); // 左节点入栈
                 if (cur.right != null) toVisit.push(cur.right); // 右节点入栈
             }
     
              while (!reversedStack.isEmpty()) {
                  cur = reversedStack.pop();
                  result.add(cur.val);
              }
             return result;
          }
    }
    

    单Stack

    申请一个栈stack,将头节点压入stack,同时设置两个变量 h 和 c,在整个流程中,h代表最近一次弹出并打印的节点,c代表当前stack的栈顶节点,初始时令h为头节点,,c为null;
    每次令c等于当前stack的栈顶节点,但是不从stack中弹出节点,此时分一下三种情况:
    (1)如果c的左孩子不为空,并且h不等于c的左孩子,也不等于c的右孩子,则吧c的左孩子压入stack中
    (2)如果情况1不成立,并且c的右孩子不为空,并且h不等于c的右孩子,则把c的右孩子压入stack中;
    (3)如果情况1和2不成立,则从stack中弹出c并打印,然后令h等于c;
    一直重复步骤2,直到stack为空.

    public static void PosOrderTwo(TreeNode<char> treeNode)
    {
        if (treeNode == null)
        {
            return;
        }
    
        Stack<TreeNode<char>> stack = new Stack<TreeNode<char>>();
        stack.Push(treeNode);
        TreeNode<char> h = treeNode;
        TreeNode<char> c = null;
        while (!(stack.Count == 0))
        {
            c = stack.Peek();
            //c结点有左孩子 并且 左孩子没被遍历(输出)过 并且 右孩子没被遍历过
            if (c.LChild != null && h != c.LChild && h != c.RChild)
                stack.Push(c.LChild);
            //c结点有右孩子 并且 右孩子没被遍历(输出)过
            else if (c.RChild != null && h != c.RChild)
                stack.Push(c.RChild);
            //c结点没有孩子结点 或者孩子结点已经被遍历(输出)过
            else
            {
                TreeNode<char> node = stack.Pop();
                Console.WriteLine(node.Data);
                h = c;
            }
        }
    }
    

    层次遍历

    public static void LevelOrder(TreeNode<char> treeNode)
    {
        if(treeNode == null)
        {
             return;
        }
        Queue<TreeNode<char>> queue = new Queue<TreeNode<char>>();
        queue.Enqueue(treeNode);
    
        while (queue.Any())
        {
            TreeNode<char> node = queue.Dequeue();
            Console.Write(node.Data);
    
            if (node.Left != null)
            {
                queue.Enqueue(node.Left);
            }
    
            if (node.Right != null)
            {
                queue.Enqueue(node.Right);
            }
        }
    }
    

    参考文献

    文献1
    文献2

    相关文章

      网友评论

          本文标题:树的遍历总结

          本文链接:https://www.haomeiwen.com/subject/calglctx.html