左程云算法课基础05二叉树课程笔记(上)--递归,非递归遍历,宽度遍历

二叉树节点结构

class Node<V>{
	V value;
	Node left;
	Node right;
}

最顶上的节点叫根节点,没有子节点的叫叶子节点

用递归和非递归两种方式实现二叉树的先序、中序、后序遍历。

递归序:按照递归顺序遍历,每个节点会遍历3次。

左程云算法课基础05二叉树课程笔记(上)--递归,非递归遍历,宽度遍历_第1张图片
又分成三种:先序,中序,后序

先序:对于所有子树,都是先打印头节点,左子树上所有节点,右子树上所有节点

为递归序加工所得,即递归遍历时第一次来到该节点时打印,其余两次什么也不做。

中序:对所有子树,先打印左节点,头节点,右节点

为递归序加工所得,即递归遍历时第二次来到该节点时打印,其余两次什么也不做。

中序:对所有子树,先打印左节点,右节点,头节点

为递归序加工所得,即递归遍历时第三次来到该节点时打印,其余两次什么也不做。
左程云算法课基础05二叉树课程笔记(上)--递归,非递归遍历,宽度遍历_第2张图片

   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.println(head.value + " ");
        preOrderRecur(head.left);
        preOrderRecur(head.right);
    }

    //递归中序遍历
    public static void inOrderRecur(Node head){
        if (head == null){
            return;
        }
        inOrderRecur(head.left);
        System.out.println(head.value + " ");
        inOrderRecur(head.right);
    }

    //递归后序遍历
    public static void posOrderRecur(Node head){
        if (head == null){
            return;
        }
        posOrderRecur(head.left);
        posOrderRecur(head.right);
        System.out.println(head.value + " ");
    }

非递归序

任何递归都可以改成非递归,

先序:准备一个栈,先把根节点放入栈中,重复一下步骤:1)从栈中弹出一个节点cur 2)打印(处理)cur 3)先将右节点压入栈中,再将左节点压入,重复

//非递归先序遍历
    public static void preOrderUnRecur(Node head){
        if (head != null){
            Stack<Node> stack = new Stack<>();
            stack.push(head);
            while (!stack.isEmpty()){
                head = stack.pop();
                System.out.println(head.value);
                if (head.right != null){
                    stack.push(head.right);
                }
                if (head.left != null){
                    stack.push(head.left);
                }
            }
        }
    }

后序1:准备一个放置栈,一个收集栈,先把根节点放入放置栈中,重复一下步骤:1)从栈中弹出一个节点cur放入收集栈 2)先将左节点压入栈中,再将右节点压入,重复, 之后打印收集栈。这一种算法

public static void posOrderUnRecur1(Node head){
        if (head != null){
            Stack<Node> stack1 = new Stack<>();//放入的栈
            Stack<Node> stack2 = new Stack<>();//收集的栈
            stack1.add(head);
            while (!stack1.isEmpty()){
                head =stack1.pop();
                stack2.add(head);
                if (head.left != null){
                    stack1.add(head.left);
                }
                if (head.right != null){
                    stack1.add(head.right);
                }
            }
            while (!stack2.empty()){
                System.out.print(stack2.pop().value + " ");
            }
        }
        System.out.println();
    }

中序:准备一个栈将其每棵子树整棵树左边界进栈,无左边界时依次弹出节点的过程中打印,然后对弹出节点的右树的左边界重复同样的操作

public static void inOrderUnRecur(Node head){
        Stack<Node> stack1 = new Stack<>();
        if (head != null){
            while (!stack1.isEmpty() || head != null) {//只要左边界上的数不为null则全部放入栈中
                if (head != null) {
                    stack1.add(head);
                    head = head.left;
                }else {//否则就弹出,并去找右边再去找对应的右边界
                    head = stack1.pop();
                    System.out.print(head.value + " ");
                    head = head.right;
                }
            }
        }
        System.out.println();
    }

如何直观的打印一颗二叉树

老师给的福利函数,直接可以打印二叉树结构,旋转90度即可

    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 widthOrder(Node head){
        Queue<Node> queue = new LinkedList<>();
        if (head == null){
            return;
        }
        queue.add(head);
        while (!queue.isEmpty()){
            Node cur = queue.poll();
            System.out.println(cur.value);
            if (cur.left != null){
                queue.add(cur.left);
            }
            if (cur.right != null){
                queue.add(cur.right);
            }
        }

求一颗二叉树的最大宽度

在宽度优先遍历的基础上设定三个变量最大宽度,当前层宽度,当前层。利用hash表,先将头节点及其层1放入,然后开始利用队列进行宽度优先遍历,利用头节点在HashMap中放入其左节点和层数,其右节点和层数,对每个遍历到的节点判断其层数与当前层是否相同,不同则是当前层宽度置为0,相同则当前层宽度++。更新最大宽度,最后返回最大宽度。

public static int getBigWidth(Node head){
        if (head == null){
            return 0;
        }
        HashMap<Node , Integer> hashMap = new HashMap<>();
        Queue<Node> queue = new LinkedList<>();
        hashMap.put(head,1);
        queue.add(head);
        int maxWidth  = 0;
        int curLevel = 0;
        int curWidth = 0;
        while (!queue.isEmpty()){
            head = queue.poll();
            if (head.left != null){
                queue.add(head.left);
                hashMap.put(head.left,hashMap.get(head) + 1);
            }
            if (head.right != null){
                queue.add(head.right);
                hashMap.put(head.right,hashMap.get(head) + 1);
            }
            if (curLevel <= hashMap.get(head)){
                curWidth = 0;
                curLevel = hashMap.get(head);
            }else {
                curWidth ++;
            }
            maxWidth = Math.max(curWidth,maxWidth);
        }
        return maxWidth;
    }

你可能感兴趣的:(算法,java,深度优先)