• 树遍历算法概述


    首先树是一种递归结构,因此递归算法很好写,关键是非递归算法。

    而非递归算法中,树的四种非递归遍历方式又是核心。下面先介绍树的四种非递归遍历算法,再介绍其他的非递归算法。

    1、层次遍历:

    这大概是最简单的了,队列结构,先进根节点,然后循环:出队列头,然后分别进左,右子树节点。如此反复,直至队列为空。

    2、先序遍历:

    单栈即可。这个在三序遍历中最简单,因为栈只需要保存右子树节点,左子树直接访问。要点:访左存右。一层while循环即可搞定。

    3、中序遍历:

    单栈即可。这个要比先序难些,因为左右子树节点都要保存在栈中,因此分清父节点是否被访问过极为重要,不然就会无限循环。

    怎么区分呢?可以这样区分:以tmp保存父节点,以tmp是否为空作为进栈条件(绝不可以tmp.left是否为空做为进栈条件,这样会分不清父节点是否访问过。不服可以写个试试),进栈后,tmp=tmp.left;出栈后,tmp=tmp.right。这样就可完美区分左右。

    由于左节点要一次性进到底,所以总共需要两层while循环。要点:左路进到底,然后退一进右。如此反复。

    4、后序遍历:

    后序遍历就必须得用符号来标识左右了。实际上中序遍历不用符号已经令我很吃惊,不过中序右子树只保存一层,因此还可以区分左右。但后序左右子树均要保存多层,不用符号就无法区分左右。

    实际上后序遍历和中序遍历很像,更实际上,三种遍历的顺序是一样的,先序因为先访问节点,所以不保存左子树,故和后两序差别较大。

    因此我们可以仿照中序遍历的写法来写后序。只不过加上符号,标明左右。

    会写中序非递归遍历,就会写后序非递归遍历。要点:左路进到底,判断符号,左则变号进右,右则退栈输出。如此反复。

    另外切记:直接以tmp != null 而不是tmp.left != null 作为左子树递进条件。写循环的要点在于一次把一层写完,而不是一次写残缺多层。

    另外:进栈时,我们是知道左右的,出栈时就不知道了。出栈想要防止重复访问,就需要特殊的访问技巧(中序)和特殊的标记符号(后序)。

    其余还有一些琐碎算法,基本都是树的几种遍历算法的应用:

    1、通过前序与中序确定二叉树。前序首节点是根节点,中序,根节点左右为左右子树。据此不断划分,递归构建即可。

    2、n个节点二叉树的个数与n个元素的出栈顺序一样,均为卡特兰树。(1/(n+1)) * C(2n,n).

    java代码如下:

    package com.company;
    
    /**
     * Build a binary tree from a generalized list.
     * input is like this:A(B(D,E(G,)),C(,F))#
     */
    public class TreeBuilder {
    
        private static class Node{
            char value;
            Node left;
            Node right;
        }
    
        /**
         * Build a binary tree from a generalized list.
         * @param glist glist is a generalized list, for example: A(B(D,E(G,)),C(,F))#
         * @return the root node of tree
         */
        public static Node creatTree(String glist){
           if (glist.isEmpty()){
               return null;
           }
           Node[] stack = new Node[glist.length()];
           int pos = 0; int top = -1;
           Node root = new Node();
           if ((glist.charAt(pos) + "").matches("[A-Z]")){ //if is upper character, push in stack
                root.value = glist.charAt(pos);
                stack[++top] = root;
            }else {
               return null;
           }
           while (glist.charAt(pos) != '#'){
               char ch = glist.charAt(pos);
               if (ch == '('){
                   pos++;
                   if ((glist.charAt(pos) + "").matches("[A-Z]")){
                       Node tmp = new Node();
                       tmp.value = glist.charAt(pos);
                       stack[top].left = tmp;
                       if (glist.charAt(pos+1) == '('){ // if has sub-tree, push in stack
                           stack[++top] = tmp;
                       }
                       pos++;
                   }else if (glist.charAt(pos) == ','){
                       stack[top].left = null;
                   }
               }else if (glist.charAt(pos) == ','){ // after ',' is right sub-tree.
                   pos++;
                   if ((glist.charAt(pos) + "").matches("[A-Z]")){
                       Node tmp = new Node();
                       tmp.value = glist.charAt(pos);
                       stack[top--].right = tmp; // pop stack
                       if (glist.charAt(pos+1) == '('){ // if has sub-tree, push in stack
                           stack[++top] = tmp;
                       }
                       pos++;
                   }else {
                       stack[top--].right = null;
                   }
               }else {
                   pos++;
               }
           }
           if (top == -1){ // test whether the result is true.
               System.out.println(true);
           }
           return root;
        }
    
    
        /**
         * Build a binary tree from a generalized list.
         * version 2, use switch grammar
         * @param glist glist is a generalized list, for example: A(B(D,E(G,)),C(,F))#
         * @return the root node of tree
         */
        public static Node creatTree2(String glist){
            if (glist.isEmpty()){
                return null;
            }
            Node[] stack = new Node[glist.length()];
            int top = -1;
            int flag = 0; // right sub-tree or left sub-tree
            int pos = 0;  // char position
            Node root = null;
            Node tmp = null;
            while (glist.charAt(pos) != '#'){
                char ch = glist.charAt(pos);
                switch (ch){
                    case '(':
                        stack[++top] = tmp;// push in
                        pos++;
                        flag = 1;  // left sub-tree
                        break;
                    case ',':
                        pos++;
                        flag = 2; // right sub-tree
                        break;
                    case ')':
                        pos++;
                        top--;  // pop out
                        break;
                    default:
                        tmp = new Node();
                        tmp.value = ch;
                        if (root == null){  // link the root
                            root = tmp;
                        }
                        if (flag == 1){
                            stack[top].left = tmp;
                        }else if (flag == 2){
                            stack[top].right = tmp;
                        }
                        pos++;
                }
            }
            return root;
        }
    
        public static void printPreTree(Node root){
            if (root != null){
                System.out.print(root.value + " ");
                printPreTree(root.left);
                printPreTree(root.right);
            }
        }
    
        /**
         * the non-recursion pre traversal of tree
         * @param root
         */
        public static void printPreTreeNonRecursion(Node root){
            Node tmp = root;
            Node[] stack = new Node[20];
            int top = -1;
            while (tmp != null || top != -1){
                if (tmp != null){
                    System.out.printf(tmp.value + " ");
                    if (tmp.right != null){
                        stack[++top] = tmp.right;
                    }
                    tmp = tmp.left;
                }else {
                    tmp = stack[top--];
                }
            }
            System.out.println();
        }
    
        /**
         * the hierarchical traversal of tree
         * @param root
         */
        public static void printHierarchical(Node root){
            Node[] queen = new Node[20];
            int head = 0;
            int tail = 0;
            Node tmp = root;
            queen[tail++%20] = tmp;
            while (tail != head){
                tmp = queen[head++%20];
                System.out.printf(tmp.value + " ");
                if (tmp.left != null){
                    queen[tail++%20] = tmp.left;
                }
                if(tmp.right != null){
                    queen[tail++%20] = tmp.right;
                }
            }
            System.out.println();
        }
    
        /**
         * 树的中序非递归遍历
         * the middle non-recursion traversal of tree
         * @param root
         */
        public static void printMidTreeNonRecursion(Node root){
            Node[] stack = new Node[20];
            int top = -1;
            Node tmp = root;
            while (tmp != null || top != -1){
                while (tmp != null){
                    stack[++top] = tmp;
                    tmp = tmp.left;
                }
                if (top != -1){
                    tmp = stack[top--];
                    System.out.printf(tmp.value + " ");
                    tmp = tmp.right;
                }
            }
            System.out.println();
        }
    
        /**
         * 树的中序递归遍历
         * the middle recursion traversal of tree
         * @param root
         */
        public static void printMidTree(Node root){
            if (root != null){
                printMidTree(root.left);
                System.out.printf(root.value + " ");
                printMidTree(root.right);
            }
        }
    
        /**
         * 树的后序递归遍历
         * the suffix recursion of traversal of tree
         */
        public static void printSufTree(Node root){
            if (root != null){
                printSufTree(root.left);
                printSufTree(root.right);
                System.out.printf(root.value + " ");
            }
        }
    
        /**
         * the suffix non-recursion traversal of tree
         */
        public static void printSufTreeNonRecursion(Node root){
            class FlagNode{
                Node node;
                int flag;
            }
            FlagNode[] stack = new FlagNode[20];
            int top = -1;
            Node tmp = root;
            while (top != -1 || tmp != null){
                while (tmp != null){
                    FlagNode flagNode = new FlagNode();
                    flagNode.node = tmp;
                    flagNode.flag = 0;
                    stack[++top] = flagNode;
                    tmp = tmp.left;
                }
                if (top != -1){
                    if (stack[top].flag == 0){
                        stack[top].flag = 1;
                        tmp = stack[top].node.right;
                    }else {
                        System.out.printf(stack[top--].node.value + " ");
                    }
                }
            }
            System.out.println();
        }
        /**
         * 以广义表的形式把树打印出来
         * @param root
         */
        public static void printGTree(Node root){
            if(root != null){
                System.out.printf(root.value + "");
                if (root.left != null || root.right != null) {
                    System.out.printf("(");
                    printGTree(root.left);
                    System.out.printf(",");
                    printGTree(root.right);
                    System.out.printf(")");
                }
            }
        }
    
        public static void main(String[] args) {
        // write your code here
            Node root =creatTree("A(B(G,H(K,L)),C(D,E(F,)))#");
            System.out.println("Pre traversal: ");
            printPreTree(root);
            System.out.println();
            printPreTreeNonRecursion(root);
    
            System.out.println(" : ");
            printHierarchical(root);
    
    
    
            Node root2 =creatTree2("A(B(G(H(K(,J(,Z)),),I),M(,N)),C(D,E(F,)))#");
            System.out.println("Mid traversal: ");
            printMidTree(root2);
            System.out.println();
            printMidTreeNonRecursion(root2);
            System.out.println("Suf traversal: ");
            printSufTree(root2);
            System.out.println();
            printSufTreeNonRecursion(root2);
        }
    }
  • 相关阅读:
    GUI树组件,表格
    GUI对话框
    java事件处理5(窗口,窗口坐监视器
    java事件处理4(焦点,键盘
    java事件处理3
    java事件处理2
    2
    sql查询语句心得
    The 2018 ACM-ICPC Chinese Collegiate Programming Contest Maximum Element In A Stack
    cf 1006E
  • 原文地址:https://www.cnblogs.com/zqiguoshang/p/6498831.html
Copyright © 2020-2023  润新知