zoukankan      html  css  js  c++  java
  • 中序线索二叉树及相关算法概述(java实现)

     中序线索二叉树就是在普通的二叉树上加上了中序线索。

    为了节省空间,只增加两个判定位。flagLeft 和 flagRight,当为0时,表示存放的是子女节点。为1时,表示存放的线索。

    其中,左节点存放中序前继,右节点存放中序后继。

    使用线索,可以有效降低二叉树遍历的复杂度。前序,中序,后序遍历都可不用递归栈实现,而付出的代价只是几个标志位。

    建立中序线索二叉树,可以用普通中序遍历实现。用一个pre保存中序前节点,在中序访问时,贯通前后即可。

    C++ pre用指针引用,java pre用对象数组保存。因为pre值要保证能在递归过程中传递

    最后注意将中序最后一个节点手动赋值。

    对于由中序线索二叉树实现树的前序、中序、后序非递归,非栈遍历。之所以能不用栈,是因为中序线索保存了相关信息。

    要注意,先找到第一个节点,然后利用中序线索找后继即可。

    对于前序,其后继为当前节点右子女走,flagRight为0的第一个节点的右子女。

    中序,后继已给出,注意同样要将flagRight为1的的节点一次遍历完。

    实际上,画个图模拟一下就清楚了。

    建立普通二叉树可根据中序、前序字符串建立的。思想是,根据前序找到根节点,然后根据中序化为左右子树,不断递归。

    在划分过程中,左子树和右子树在前序、中序字符串中都是连续的。并且中序和前序字符串长度总是相等。可根据这一点简化划分。

    下面给出java代码实现:

    package com.company;
    
    /**
     * 根据中序及前序建立二叉树
     * 根据后序及前序建立二叉树
     * 二叉树中序索引化
     * Created by zqiguo on 2017/3/8.
     */
    public class IndexBinaryTree {
        private static class IndexNode{
            char value;
            IndexNode left;
            IndexNode right;
            boolean flagLeft;
            boolean flagRight;
        }
    
        /**
         * 建立中序索引二叉树的公用接口,注意手动赋值最后一节点。
         * @param root
         */
        public static void creatMidIndexTree(IndexNode root){
            if (root == null) {
                return;
            }
            IndexNode[] pre = new IndexNode[1];
            creatMidIndexTree(root, pre);
            pre[0].right = null;
            pre[0].flagRight = true;
        }
        /**
         * 建立中序索引,之所以pre 为[]类型,为了在递归中传递值。
         * pre保存前一中序节点,这样就足够,注意要手动将最后一个节点右子树赋值。
         * 左节点走到底,脑中模拟一遍,就出结果了。
         * @param root 根节点
         * @param pre IndexNode[], 数组容量为1,用于在递归中保存中序前一节点
         *
         */
        private static void creatMidIndexTree(IndexNode root, IndexNode[] pre){
            if (root == null){
                return;
            }
            creatMidIndexTree(root.left, pre);
            if (root.left == null){
                root.left = pre[0];
                root.flagLeft = true;
            }
            if (pre[0] != null && pre[0].right == null){
                pre[0].right = root;
                pre[0].flagRight = true;
            }
            pre[0] = root;
            creatMidIndexTree(root.right, pre);
        }
    
    
        /**
         * 根据中序和前序建立二叉树
         * @param pre  String 前序序列
         * @param mid  String 中序序列
         * @return  根节点
         */
        public static IndexNode creatTreeByPreAndMid(String pre, String mid){
            IndexNode indexNode = null;
            if(pre.length() > 0){
                indexNode = new IndexNode();
                indexNode.value = pre.charAt(0);
                String left = mid.substring(0, mid.indexOf(indexNode.value));
                int i = 1;
                while (i < pre.length()){
                    if (left.contains(pre.charAt(i) + "")){
                        i++;
                    }else {
                        break;
                    }
                }
                String preLeft = pre.substring(1,i);
                String preRight = pre.substring(i,pre.length());
                String right = mid.substring(mid.indexOf(indexNode.value)+1, mid.length());
                indexNode.left = creatTreeByPreAndMid(preLeft,left);
                indexNode.right = creatTreeByPreAndMid(preRight,right);
            }
            return indexNode;
        }
    
        /**
         * 根据后序和中序建立二叉树
         * @param mid
         * @param suf
         * @return
         */
        public static IndexNode createTreebyMidAndSuf(String mid, String suf){
            IndexNode root = null;
            if (suf.length() > 0){
                root = new IndexNode();
                root.value = suf.charAt(suf.length()-1);
                String midLeft = mid.substring(0,mid.indexOf(suf.charAt(suf.length()-1)));
                String midRight = mid.substring(mid.indexOf(suf.charAt(suf.length()-1))+1, mid.length());
                String sufLeft = suf.substring(0,midLeft.length());
                String sufRight = suf.substring(midLeft.length(),suf.length()-1);
                root.left = createTreebyMidAndSuf(midLeft,sufLeft);
                root.right = createTreebyMidAndSuf(midRight,sufRight);
            }
            return root;
        }
    
        /**
         * 中序非递归遍历
         * @param root
         */
        public static void printMidNonStack(IndexNode root){
            IndexNode[] stack = new IndexNode[20];
            int top = -1;
            IndexNode 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();
        }
    
        public static void printMid(IndexNode root){
            if (root != null){
                printMid(root.left);
                System.out.printf(root.value + " ");
                printMid(root.right);
            }
        }
    
        /**
         * 前序非递归遍历
         * @param root
         */
        public static void printPreNonStack(IndexNode root){
            IndexNode tmp = root;
            IndexNode[] stack = new IndexNode[20];
            int top = -1;
            while (top != -1 || tmp != null){
                if (tmp == null){
                    tmp = stack[top--];
                }else {
                    System.out.printf(tmp.value + " ");
                    if (tmp.right != null){
                        stack[++top] = tmp.right;
                    }
                    tmp = tmp.left;
                }
            }
            System.out.println();
        }
    
        public static void printPre(IndexNode root){
            if (root != null){
                System.out.printf(root.value + " ");
                printPre(root.left);
                printPre(root.right);
            }
        }
    
        public static void printSuf(IndexNode root){
            if (root != null){
                printSuf(root.left);
                printSuf(root.right);
                System.out.printf(root.value + " ");
            }
        }
    
        /**
         * 后序非递归遍历
         * @param root
         */
        public static void printSufNonStack(IndexNode root){
            class FlagIndexNode{
                IndexNode indexNode;
                boolean right;
            }
            FlagIndexNode[] stack = new FlagIndexNode[20];
            int top = -1;
            IndexNode tmp = root;
            while (top != -1 || tmp != null){
                while (tmp != null){
                    FlagIndexNode flagIndexNode = new FlagIndexNode();
                    flagIndexNode.indexNode = tmp;
                    stack[++top] = flagIndexNode;
                    tmp = tmp.left;
                }
                if (stack[top].right == false){
                    stack[top].right = true;
                    tmp = stack[top].indexNode.right;
                }else {
                    System.out.printf(stack[top--].indexNode.value + " ");
                }
            }
            System.out.println();
        }
    
        /**
         * 使用中序索引二叉树来实现前序遍历。不用栈。
         * 方法要点在于找出节点的前序后继。节点的前序后继就是节点中序后继标志不为TRUE的第一个节点的右子树。
         * 画一个树图示意一下,就明白了。
         * @param root
         */
        public static void printPreOrderUseIndex(IndexNode root){
            IndexNode tmp = root;
            while (tmp != null){
                while (tmp.flagLeft != true) {
                    System.out.printf(tmp.value + " ");
                    tmp = tmp.left;
                }
                System.out.printf(tmp.value + " ");
                if (tmp.flagRight != true){
                    tmp = tmp.right;
                }else {
                    while (tmp.flagRight == true && tmp.right != null){
                        tmp = tmp.right;
                    }
                    tmp = tmp.right;
                }
            }
            System.out.println();
        }
    
        /**
         * Use middle indexed binary tree to print middle traversal order.
         * @param root the root of tree
         */
        public static void printMidOrderUseIndex(IndexNode root){
            IndexNode tmp = root;
            while (tmp != null){
                while (tmp.flagLeft != true){
                    tmp = tmp.left;
                }
                System.out.printf(tmp.value + " ");
                while (tmp.flagRight == true && tmp.right != null){
                    tmp = tmp.right;
                    System.out.printf(tmp.value + " ");
                }
                tmp = tmp.right;
            }
        }
    
        public static void main(String[] args){
            String pre = "ABDGCEF";
            String mid = "BGDACEF";
            String suf = "GDBFECA";
            IndexNode root = creatTreeByPreAndMid(pre,mid);
            IndexNode root2 = createTreebyMidAndSuf(mid,suf);
    
            printMid(root);
            System.out.println();
            printMidNonStack(root);
            printMid(root2);
            System.out.println();
            printMidNonStack(root2);
            System.out.println();
            printPre(root);
            System.out.println();
            printPreNonStack(root2);
            printPre(root2);
            System.out.println();
            System.out.println();
    
            printSuf(root);
            System.out.println();
            printSufNonStack(root);
    
            System.out.println();
            System.out.println();
            printPreNonStack(root);
            printMidNonStack(root);
            creatMidIndexTree(root);
            printPreOrderUseIndex(root);
            printMidOrderUseIndex(root);
    
        }
    }
    

      

  • 相关阅读:
    根据前序遍历和中序遍历重建二叉树
    Java内部类
    Java浅克隆和深度克隆
    【leetcode】1354. Construct Target Array With Multiple Sums
    【leetcode】1352. Product of the Last K Numbers
    【leetcode】1351. Count Negative Numbers in a Sorted Matrix
    【leetcode】1342. Number of Steps to Reduce a Number to Zero
    【leetcode】1343. Number of Sub-arrays of Size K and Average Greater than or Equal to Threshold
    【leetcode】1344. Angle Between Hands of a Clock
    【leetcode】1346. Check If N and Its Double Exist
  • 原文地址:https://www.cnblogs.com/zqiguoshang/p/6531165.html
Copyright © 2011-2022 走看看