zoukankan      html  css  js  c++  java
  • 初级5 二叉树

    题目一:实现二叉树的先序、中序、后序遍历,包括递归方式和非递归方式

     递归版:递归来到每个节点的顺序

    前序遍历  打印时机放在第1次来到这个节点的时候

     中序遍历  打印时机放在第2次来到这个节点的时候

     后序遍历  打印时机放在第3次来到这个节点的时候

        // 递归版本--先序遍历
        public static void preOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            // System.out.print(head.value + " ");
            preOrderRecur(head.left);
            preOrderRecur(head.right);
        }

    非递归版:stack栈

    1,2,4,5,3,6,7

        // 非递归--前序遍历
        public static void preOrderUnRecur(Node head) {
            System.out.print("pre-order: ");
            if (head != null) {
                Stack<Node> stack = new Stack<Node>();
                stack.add(head);
                while (!stack.isEmpty()) {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    
                    //如果有右孩子,先压右
                    // 如果有左孩子,后压左
                    if (head.right != null) {
                        stack.push(head.right);
                    }
                    if (head.left != null) {
                        stack.push(head.left);
                    }
                }
            }
            System.out.println();
        }

    中左右被 模拟出来了

     先压右后压左

    先弹左,后弹右

     

    为什么不用队列?

    递归函数就是一种栈

     

    二叉树只有从上到下的路径,没有回去的路径

     非递归--中序遍历

        public static void inOrderUnRecur(Node head) {
            System.out.print("in-order: ");
            if (head != null) {
                Stack<Node> stack = new Stack<Node>();
                while (!stack.isEmpty() || head != null) {
                    if (head != null) {
                        stack.push(head);
                        head = head.left;
                    } else {
                        head = stack.pop();
                        System.out.print(head.value + " ");
                        head = head.right;
                    }
                }
            }
            System.out.println();
        }

    head不等于空

     当前节点会把自己左边界全部压入栈中,head = head.left

    head == null 停止

    当前节点为空,从栈中拿出一个,打印,往右移动

    当前节点不为空,当前压入栈中,节点往左移动

     极端例子

    整棵树可以被左边界分解的

    非递归--后序遍历

    左右中  ---> 中右左----> 中左右(当前节点,先压左,再压右)   

    先不打印,放入栈中,然后逆序输出

    方法1:两个栈

        public static void posOrderUnRecur1(Node head) {
            System.out.print("pos-order: ");
            if (head != null) {
                Stack<Node> s1 = new Stack<Node>();
                Stack<Node> s2 = new Stack<Node>();
                s1.push(head);
                while (!s1.isEmpty()) {
                    head = s1.pop();
                    // s2.push(head);  打印时机,放入辅助栈中,
                    if (head.left != null) {
                        s1.push(head.left);    // 左不为空,先压左
                    } 
                    if (head.right != null) {
                        s1.push(head.right);
                    }
                }
                while (!s2.isEmpty()) {
                    System.out.print(s2.pop().value + " ");   // 逆序打印栈
                }
            }
            System.out.println();
        }

     方法2:1个栈

    纯属炫技

    完整java代码

    package class_04;
    
    import java.util.Stack;
    
    public class Code_01_PreInPosTraversal {
    
        public static class Node {
            public int value;
            public Node left;
            public Node right;
    
            public Node(int data) {
                this.value = data;
            }
        }
    
    
        // 递归版本--先序遍历
        public static void preOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            // System.out.print(head.value + " ");
            preOrderRecur(head.left);
            preOrderRecur(head.right);
        }
    
        public static void inOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            inOrderRecur(head.left);
            System.out.print(head.value + " ");
            inOrderRecur(head.right);
        }
    
        public static void posOrderRecur(Node head) {
            if (head == null) {
                return;
            }
            posOrderRecur(head.left);
            posOrderRecur(head.right);
            System.out.print(head.value + " ");
        }
    
        // 非递归--前序遍历
        public static void preOrderUnRecur(Node head) {
            System.out.print("pre-order: ");
            if (head != null) {
                Stack<Node> stack = new Stack<Node>();
                stack.add(head);
                while (!stack.isEmpty()) {
                    head = stack.pop();
                    System.out.print(head.value + " ");
                    
                    //如果有右孩子,先压右
                    // 如果有左孩子,后压左
                    if (head.right != null) {
                        stack.push(head.right);
                    }
                    if (head.left != null) {
                        stack.push(head.left);
                    }
                }
            }
            System.out.println();
        }
    
        // 非递归---后序
        // 方法1:两个栈
        public static void inOrderUnRecur(Node head) {
            System.out.print("in-order: ");
            if (head != null) {
                Stack<Node> stack = new Stack<Node>();
                while (!stack.isEmpty() || head != null) {
                    if (head != null) {
                        stack.push(head);
                        head = head.left;
                    } else {
                        head = stack.pop();
                        System.out.print(head.value + " ");
                        head = head.right;
                    }
                }
            }
            System.out.println();
        }
    
        
        // 方法2:一个栈,炫技
        public static void posOrderUnRecur1(Node head) {
            System.out.print("pos-order: ");
            if (head != null) {
                Stack<Node> s1 = new Stack<Node>();
                Stack<Node> s2 = new Stack<Node>();
                s1.push(head);
                while (!s1.isEmpty()) {
                    head = s1.pop();
                    // s2.push(head);  打印时机,放入辅助栈中,
                    if (head.left != null) {
                        s1.push(head.left);    // 左不为空,先压左
                    } 
                    if (head.right != null) {
                        s1.push(head.right);
                    }
                }
                while (!s2.isEmpty()) {
                    System.out.print(s2.pop().value + " ");   // 逆序打印栈
                }
            }
            System.out.println();
        }
    
        public static void posOrderUnRecur2(Node h) {
            System.out.print("pos-order: ");
            if (h != null) {
                Stack<Node> stack = new Stack<Node>();
                stack.push(h);
                Node c = null;
                while (!stack.isEmpty()) {
                    c = stack.peek();
                    if (c.left != null && h != c.left && h != c.right) {
                        stack.push(c.left);
                    } else if (c.right != null && h != c.right) {
                        stack.push(c.right);
                    } else {
                        System.out.print(stack.pop().value + " ");
                        h = c;
                    }
                }
            }
            System.out.println();
        }
    
        public static void main(String[] args) {
            Node head = new Node(5);
            head.left = new Node(3);
            head.right = new Node(8);
            head.left.left = new Node(2);
            head.left.right = new Node(4);
            head.left.left.left = new Node(1);
            head.right.left = new Node(7);
            head.right.left.left = new Node(6);
            head.right.right = new Node(10);
            head.right.right.left = new Node(9);
            head.right.right.right = new Node(11);
    
            // recursive
            System.out.println("==============recursive==============");
            System.out.print("pre-order: ");
            preOrderRecur(head);
            System.out.println();
            System.out.print("in-order: ");
            inOrderRecur(head);
            System.out.println();
            System.out.print("pos-order: ");
            posOrderRecur(head);
            System.out.println();
    
            // unrecursive
            System.out.println("============unrecursive=============");
            preOrderUnRecur(head);
            inOrderUnRecur(head);
            posOrderUnRecur1(head);
            posOrderUnRecur2(head);
    
        }
    
    }

    题目二:如何直观的打印一颗二叉树(福利)

       还原不了整棵树

    package class_04;
    
    public class Code_02_PrintBinaryTree {
    
        public static class Node {
            public int value;
            public Node left;
            public Node right;
    
            public Node(int data) {
                this.value = data;
            }
        }
    
        public static void printTree(Node head) {
            System.out.println("Binary Tree:");
            printInOrder(head, 0, "H", 17);
            System.out.println();
        }
    
        public static void printInOrder(Node head, int height, String to, int len) {
            if (head == null) {
                return;
            }
            printInOrder(head.right, height + 1, "v", len);
            String val = to + head.value + to;
            int lenM = val.length();
            int lenL = (len - lenM) / 2;
            int lenR = len - lenM - lenL;
            val = getSpace(lenL) + val + getSpace(lenR);
            System.out.println(getSpace(height * len) + val);
            printInOrder(head.left, height + 1, "^", len);
        }
    
        public static String getSpace(int num) {
            String space = " ";
            StringBuffer buf = new StringBuffer("");
            for (int i = 0; i < num; i++) {
                buf.append(space);
            }
            return buf.toString();
        }
    
        public static void main(String[] args) {
            Node head = new Node(1);
            head.left = new Node(-222222222);
            head.right = new Node(3);
            head.left.left = new Node(Integer.MIN_VALUE);
            head.right.left = new Node(55555555);
            head.right.right = new Node(66);
            head.left.left.right = new Node(777);
            printTree(head);
    
            head = new Node(1);
            head.left = new Node(2);
            head.right = new Node(3);
            head.left.left = new Node(4);
            head.right.left = new Node(5);
            head.right.right = new Node(6);
            head.left.left.right = new Node(7);
            printTree(head);
    
            head = new Node(1);
            head.left = new Node(1);
            head.right = new Node(1);
            head.left.left = new Node(1);
            head.right.left = new Node(1);
            head.right.right = new Node(1);
            head.left.left.right = new Node(1);
            printTree(head);
    
        }
    
    }

     

    题目三:在二叉树中找到一个节点的后继节点

    【题目】 现在有一种新的二叉树节点类型如下:
    public class Node { public int value; public Node left;
    public Node right; public Node parent;
    public Node(int data) { this.value = data; }
    }
    该结构比普通二叉树节点结构多了一个指向父节点的parent指针。假
    设有一 棵Node类型的节点组成的二叉树,树中每个节点的parent指针
    都正确地指向 自己的父节点,头节点的parent指向null。只给一个在
    二叉树中的某个节点 node,请实现返回node的后继节点的函数。在二
    叉树的中序遍历的序列中, node的下一个节点叫作node的后继节点。

     新类型节点

     中序遍历中:

     问题描述:如果给了5,如何找到1,不用遍历整棵树

     

    结论:

      X 如果有右孩子,右子树

      X 的后继节点一定是它右子树上的最左节点

    原因是:中序 : 左中右

    X 没有右子树,

    找他的parent,如果X是父的右子树,则继续

    直到找到,X是父的左子树, 停止

    则后继节点是parent

    package class_04;
    
    public class Code_03_SuccessorNode {
    
        public static class Node {
            public int value;
            public Node left;
            public Node right;
            public Node parent;
    
            public Node(int data) {
                this.value = data;
            }
        }
    
        public static Node getSuccessorNode(Node node) {
            if (node == null) {
                return node;
            }
            if (node.right != null) {
                return getLeftMost(node.right);  
            } else {    // 没有右子树
                Node parent = node.parent;
                while (parent != null && parent.left != node) {   // 有些节点没有后继,7的后继是Null
                    node = parent;
                    parent = node.parent;
                }
                return parent;   // 节点的后继
            }
        }
    
        public static Node getLeftMost(Node node) {  // 找到该子树的最左节点
            if (node == null) {
                return node;
            }
            while (node.left != null) {
                node = node.left;
            }
            return node;
        }
    
        public static void main(String[] args) {
            Node head = new Node(6);
            head.parent = null;
            head.left = new Node(3);
            head.left.parent = head;
            head.left.left = new Node(1);
            head.left.left.parent = head.left;
            head.left.left.right = new Node(2);
            head.left.left.right.parent = head.left.left;
            head.left.right = new Node(4);
            head.left.right.parent = head.left;
            head.left.right.right = new Node(5);
            head.left.right.right.parent = head.left.right;
            head.right = new Node(9);
            head.right.parent = head;
            head.right.left = new Node(8);
            head.right.left.parent = head.right;
            head.right.left.left = new Node(7);
            head.right.left.left.parent = head.right.left;
            head.right.right = new Node(10);
            head.right.right.parent = head.right;
    
            Node test = head.left.left;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.left.left.right;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.left;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.left.right;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.left.right.right;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.right.left.left;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.right.left;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.right;
            System.out.println(test.value + " next: " + getSuccessorNode(test).value);
            test = head.right.right; // 10's next is null
            System.out.println(test.value + " next: " + getSuccessorNode(test));
        }
    
    }

    前驱节点

    有左子树,左子树是最右节点

    Node是当前父节点的右孩子,就停止

    左神语录

    面试5面, 2~3道题

    迅速把面试官的题库挖空,还有吗,我要打10个

     

    题目四:介绍二叉树的序列化和反序列化

    data struct ----> 文件

    方法1:_ #

    序列化

    _ 代表 分割, # 代表Null

     如何区分?

    package class_04;
    
    import java.util.LinkedList;
    import java.util.Queue;
    
    public class Code_04_SerializeAndReconstructTree {
    
        public static class Node {
            public int value;
            public Node left;
            public Node right;
    
            public Node(int data) {
                this.value = data;
            }
        }
    
        public static String serialByPre(Node head) {
            if (head == null) {
                return "#!";
            }
            String res = head.value + "!";
            res += serialByPre(head.left);   // 当前节点的左树返回个字符串
            res += serialByPre(head.right);   // 右树返回个字符串
            return res;
        }
    
        public static Node reconByPreString(String preStr) {
            String[] values = preStr.split("!");
            Queue<String> queue = new LinkedList<String>();
            for (int i = 0; i != values.length; i++) {
                queue.offer(values[i]);
            }
            return reconPreOrder(queue);
        }
    
        public static Node reconPreOrder(Queue<String> queue) {
            String value = queue.poll();
            if (value.equals("#")) {
                return null;
            }
            Node head = new Node(Integer.valueOf(value));
            head.left = reconPreOrder(queue);
            head.right = reconPreOrder(queue);
            return head;
        }
    
        public static String serialByLevel(Node head) {
            if (head == null) {
                return "#!";
            }
            String res = head.value + "!";
            Queue<Node> queue = new LinkedList<Node>();
            queue.offer(head);
            while (!queue.isEmpty()) {
                head = queue.poll();
                if (head.left != null) {
                    res += head.left.value + "!";
                    queue.offer(head.left);
                } else {
                    res += "#!";
                }
                if (head.right != null) {
                    res += head.right.value + "!";
                    queue.offer(head.right);
                } else {
                    res += "#!";
                }
            }
            return res;
        }
    
        public static Node reconByLevelString(String levelStr) {
            String[] values = levelStr.split("!");
            int index = 0;
            Node head = generateNodeByString(values[index++]);
            Queue<Node> queue = new LinkedList<Node>();
            if (head != null) {
                queue.offer(head);
            }
            Node node = null;
            while (!queue.isEmpty()) {
                node = queue.poll();
                node.left = generateNodeByString(values[index++]);
                node.right = generateNodeByString(values[index++]);
                if (node.left != null) {
                    queue.offer(node.left);
                }
                if (node.right != null) {
                    queue.offer(node.right);
                }
            }
            return head;
        }
    
        public static Node generateNodeByString(String val) {
            if (val.equals("#")) {
                return null;
            }
            return new Node(Integer.valueOf(val));
        }
    
        // for test -- print tree
        public static void printTree(Node head) {
            System.out.println("Binary Tree:");
            printInOrder(head, 0, "H", 17);
            System.out.println();
        }
    
        public static void printInOrder(Node head, int height, String to, int len) {
            if (head == null) {
                return;
            }
            printInOrder(head.right, height + 1, "v", len);
            String val = to + head.value + to;
            int lenM = val.length();
            int lenL = (len - lenM) / 2;
            int lenR = len - lenM - lenL;
            val = getSpace(lenL) + val + getSpace(lenR);
            System.out.println(getSpace(height * len) + val);
            printInOrder(head.left, height + 1, "^", len);
        }
    
        public static String getSpace(int num) {
            String space = " ";
            StringBuffer buf = new StringBuffer("");
            for (int i = 0; i < num; i++) {
                buf.append(space);
            }
            return buf.toString();
        }
    
        public static void main(String[] args) {
            Node head = null;
            printTree(head);
    
            String pre = serialByPre(head);
            System.out.println("serialize tree by pre-order: " + pre);
            head = reconByPreString(pre);
            System.out.print("reconstruct tree by pre-order, ");
            printTree(head);
    
            String level = serialByLevel(head);
            System.out.println("serialize tree by level: " + level);
            head = reconByLevelString(level);
            System.out.print("reconstruct tree by level, ");
            printTree(head);
    
            System.out.println("====================================");
    
            head = new Node(1);
            printTree(head);
    
            pre = serialByPre(head);
            System.out.println("serialize tree by pre-order: " + pre);
            head = reconByPreString(pre);
            System.out.print("reconstruct tree by pre-order, ");
            printTree(head);
    
            level = serialByLevel(head);
            System.out.println("serialize tree by level: " + level);
            head = reconByLevelString(level);
            System.out.print("reconstruct tree by level, ");
            printTree(head);
    
            System.out.println("====================================");
    
            head = new Node(1);
            head.left = new Node(2);
            head.right = new Node(3);
            head.left.left = new Node(4);
            head.right.right = new Node(5);
            printTree(head);
    
            pre = serialByPre(head);
            System.out.println("serialize tree by pre-order: " + pre);
            head = reconByPreString(pre);
            System.out.print("reconstruct tree by pre-order, ");
            printTree(head);
    
            level = serialByLevel(head);
            System.out.println("serialize tree by level: " + level);
            head = reconByLevelString(level);
            System.out.print("reconstruct tree by level, ");
            printTree(head);
    
            System.out.println("====================================");
    
            head = new Node(100);
            head.left = new Node(21);
            head.left.left = new Node(37);
            head.right = new Node(-42);
            head.right.left = new Node(0);
            head.right.right = new Node(666);
            printTree(head);
    
            pre = serialByPre(head);
            System.out.println("serialize tree by pre-order: " + pre);
            head = reconByPreString(pre);
            System.out.print("reconstruct tree by pre-order, ");
            printTree(head);
    
            level = serialByLevel(head);
            System.out.println("serialize tree by level: " + level);
            head = reconByLevelString(level);
            System.out.print("reconstruct tree by level, ");
            printTree(head);
    
            System.out.println("====================================");
    
        }
    }

     反序列化

     

     方法2:按层序列化

    题目六:判断一棵二叉树是否是平衡二叉树

  • 相关阅读:
    模板引擎使用详解:包含公共模板
    ThinkPHP3.2 常量参考
    ThinkPHP的全部配置选项
    报错compile_str() flow.php on line 375的解决方法
    mysql如何更新一个表中的某个字段值等于另一个表的某个字段值
    Mac下新安装的MySQL无法登陆root用户解决方法
    IOS-第三方开源库
    IOS-每个程序员的编程之路上都应该看这11本书
    IOS-程序员和设计师必备的20个CSS工具
    IOS-2016年最好的15个Web设计和开发工具
  • 原文地址:https://www.cnblogs.com/venicid/p/10061891.html
Copyright © 2011-2022 走看看