1.树的基本遍历
// 1 // 2 3 // 4 5 6 7 public static void main(String[] args){ Tree<Integer> root = new Tree<>(1); root.left =new Tree<>(2); root.left.left =new Tree<>(4); root.left.right =new Tree<>(5); root.right =new Tree<>(3); root.right.left =new Tree<>(6); root.right.right =new Tree<>(7); System.out.print("前序遍历:"); preOrder(root); System.out.println(); System.out.print("中序遍历:"); inOrder(root); System.out.println(); System.out.print("后序遍历:"); postOrder(root); System.out.println(); System.out.print("层序遍历:"); levelOrder(root); System.out.println(); System.out.print("前序遍历:"); preOrderNoRecurisive(root); System.out.println(); System.out.print("中序遍历:"); inOrderNoRecurisive(root); System.out.println(); System.out.print("后序遍历:"); postOrderNoRecurisive(root); System.out.println(); } public static class Tree<T>{ private T val; private Tree<T> left; private Tree<T> right; public Tree(T val){ this.val = val; } } //前序遍历 public static void preOrder(Tree<Integer> root){ if(root == null){ return; } System.out.print(root.val +" "); preOrder(root.left); preOrder(root.right); } //前序遍历 public static void preOrderNoRecurisive(Tree<Integer> root){ if(root == null){ return; } //只要当前节点不为空或者栈非空,就入栈;当前节点若为空,就弹栈并指向右子树 Stack<Tree<Integer>> stack = new Stack<>(); Tree<Integer> cur = root; while(cur != null || !stack.isEmpty()){ if(cur!=null){ //遍历当前节点 System.out.print(cur.val +" "); //入栈 stack.push(cur); cur = cur.left; }else{ //弹栈 cur = stack.pop().right; } } } //中序遍历 public static void inOrderNoRecurisive(Tree<Integer> root){ if(root == null){ return; } //只要当前节点不为空或者栈非空,就入栈;当前节点若为空,就弹栈并指向右子树 Stack<Tree<Integer>> stack = new Stack<>(); Tree<Integer> cur = root; while(cur != null || !stack.isEmpty()){ if(cur!=null){ //入栈 stack.push(cur); cur = cur.left; }else{ //遍历当前节点 System.out.print(stack.peek().val +" "); //弹栈 cur = stack.pop().right; } } } //后序遍历 public static void postOrderNoRecurisive(Tree<Integer> root){ if(root == null){ return; } //需要判断上次访问的节点是位于左子树,还是右子树。 //若是位于左子树,则需跳过根节点,先进入右子树,再回头访问根节点; //若是位于右子树,则直接访问根节点 Stack<Tree<Integer>> stack = new Stack<>(); Tree<Integer> cur = root; Tree<Integer> preVisited = null;//区分是左子树还是右子树返回的 while(cur != null || !stack.isEmpty()){ if(cur!=null){ //入栈 stack.push(cur); cur = cur.left; }else{ //当前节点指向栈顶右子树 cur = stack.peek().right; //判断右子树是否被访问过 if(cur !=null && cur != preVisited){ //右子树没有被访问过,就把右子树的所有左子树入栈 stack.push(cur); cur = cur.left; }else{ //右子树已经被访问过 preVisited = stack.pop(); //遍历当前节点 System.out.print(preVisited.val +" "); //弹栈 cur = null; } } } } //中序遍历 public static void inOrder(Tree<Integer> root){ if(root == null){ return; } inOrder(root.left); System.out.print(root.val +" "); inOrder(root.right); } //后序遍历 public static void postOrder(Tree<Integer> root){ if(root == null){ return; } postOrder(root.left); postOrder(root.right); System.out.print(root.val +" "); } //层序遍历 public static void levelOrder(Tree<Integer> root){ //队列存储元素 Queue<Tree<Integer>> queue = new LinkedList<>(); if(root == null){ return; } Tree<Integer> temp = null; //根先入队列 queue.offer(root); while(!queue.isEmpty()){ //先取队头元素 temp = queue.poll(); //访问该元素 if(temp !=null){ System.out.print(temp.val +" "); if(temp.left!=null){ queue.offer(temp.left); } if(temp.right!=null){ queue.offer(temp.right); } } } }
注:二叉树后序遍历,将要被访问的节点的父节点均存储在栈里面,因此,弹栈就可以获取这条路径;
2.二叉树重建
public static void main(String[] args){ int[] pre={1,2,4,5,3}; int[] in={4,2,5,1,3}; Tree root = construct(pre,in); System.out.print("前序遍历:"); preOrder(root); System.out.println(); System.out.print("中序遍历:"); inOrder(root); System.out.println(); System.out.print("后序遍历:"); postOrder(root); System.out.println(); } //重建二叉树 public static Tree construct(int[] preorder, int[] inorder){ if(preorder == null || inorder == null || preorder.length == 0 || inorder.length == 0 || preorder.length != inorder.length) return null; return constructCore(preorder, 0, inorder, 0, preorder.length); } public static Tree constructCore(int[] preorder, int preorder_start, int[] inorder, int inorder_start, int length){ if(preorder == null || inorder == null || preorder.length == 0 || preorder.length != inorder.length) return null; if(0 >= length){ return null; } int inorderRootIndex = -1; //前序和中序获取根节点位置 for(int i = inorder_start; i < inorder_start + length; i++){ if(inorder[i] == preorder[preorder_start]){ inorderRootIndex = i; break; } } int left_length = inorderRootIndex - inorder_start; //获取根节点 Tree<Object> node = new Tree<>(preorder[preorder_start]); //递归构建左子树 node.left = constructCore(preorder, preorder_start + 1, inorder, inorder_start, left_length); node.right = constructCore(preorder, preorder_start + left_length + 1, inorder, inorderRootIndex + 1, length - left_length -1); return node; }
3.中序遍历二叉树的下一个节点
//二叉树中序遍历的下一个节点 public static class TreeWithFatherPointer<T>{ private T val; private TreeWithFatherPointer left; private TreeWithFatherPointer right; private TreeWithFatherPointer father; public TreeWithFatherPointer(T val){ this.val = val; } } public static TreeWithFatherPointer getNext(TreeWithFatherPointer root){ if(root == null){ return null; } //只要有右子树,就循环查找右子树的最左子树 if(root.right != null){ root = root.right; while(root.left != null){ root = root.left; } return root; } //没有右子树,就向上查找一个节点,满足该节点的父节点的左海子节点恰好是该节点,则该父节点就是下一个节点 while(root.father !=null){ if(root.father.left == root) return root.father; root = root.father; } return null; } public static void main(String [] args){ // 1 // 2 3 // 4 5 TreeWithFatherPointer<Integer> root = new TreeWithFatherPointer<>(1); root.left = new TreeWithFatherPointer(2); root.left.father = root; root.right = new TreeWithFatherPointer(3); root.right.father = root; root.left.left = new TreeWithFatherPointer(4); root.left.left.father = root.left.left; root.left.right = new TreeWithFatherPointer(5); root.left.right.father = root.left.right; System.out.println(getNext(root.left).val); }