數據結構與算法目錄(http://www.javashuo.com/article/p-qvigrlkr-da.html)html
二叉樹遍歷分爲:前序遍歷、中序遍歷、後序遍歷。即父結點的訪問順序java
基本思想:先訪問根結點,再先序遍歷左子樹,最後再先序遍歷右子樹即根—左—右。圖中前序遍歷結果是:1,2,4,5,7,8,3,6。node
// 遞歸實現前序遍歷 public void preOrder() { System.out.printf("%s ", value); if (left != null) { left.preOrder1(); } if (right != null) { right.preOrder1(); } } // 非遞歸實現前序遍歷 public void preOrder1() { TreeNode<E> head = this; Stack<TreeNode<E>> stack = new Stack(); stack.push(head); while (!stack.isEmpty()) { TreeNode<E> pop = stack.pop(); System.out.printf("%s ", head.value); if (pop.right != null) { stack.push(pop.right); } if (pop.left != null) { stack.push(pop.left); } } }
// 遞歸實現中序遍歷 public void midOrder() { if (left != null) { left.preOrder1(); } System.out.printf("%s ", value); if (right != null) { right.preOrder1(); } } // 非遞歸實現中序遍歷 public void midOrder1() { TreeNode<E> head = this; Stack<TreeNode<E>> stack = new Stack(); while (!stack.isEmpty() || head != null) { if (head != null) { // 先將左結點所有入棧 stack.push(head); head = head.left; } else { // 左結點所有入棧後就須要依次彈出,並處理右結點 head = stack.pop(); System.out.printf("%s ", head.value); head = head.right; } } }
// 遞歸實現後序遍歷 public void postOrder() { if (left != null) { left.preOrder1(); } if (right != null) { right.preOrder1(); } System.out.printf("%s ", value); } // 非遞歸實現後序遍歷 public void postOrder2() { TreeNode<E> head = this; Stack<TreeNode<E>> stack1 = new Stack(); Stack<TreeNode<E>> stack2 = new Stack(); stack1.push(head); while (!stack1.isEmpty()) { TreeNode<E> tmp = stack1.pop(); stack2.push(tmp); if (tmp.left != null) { stack1.push(tmp.left); } if (tmp.right != null) { stack1.push(tmp.right); } } while (!stack2.isEmpty()) { TreeNode<E> tmp = stack2.pop(); System.out.printf("%s ", tmp.value); } }
public void levelOrder() { TreeNode<E> head = this; Queue<TreeNode<E>> queue = new ArrayDeque<>(); queue.offer(head); while (!queue.isEmpty()) { for (int i = 0; i < queue.size(); i++) { TreeNode<E> tmp = queue.poll(); System.out.printf(String.valueOf(tmp.value) + " "); if (tmp.left != null) { queue.offer(tmp.left); } if (tmp.right != null) { queue.offer(tmp.right); } } } }
// 非遞歸求樹的最大和最小深度 public int maxLevel() { int level = 0; TreeNode<E> head = this; Queue<TreeNode<E>> queue = new ArrayDeque<>(); queue.offer(head); while (!queue.isEmpty()) { for (int i = 0; i < queue.size(); i++) { level++; TreeNode<E> tmp = queue.poll(); if (tmp.left != null) { queue.offer(tmp.left); } if (tmp.right != null) { queue.offer(tmp.right); } } } return level; } public int minLevel() { int level = 0; TreeNode<E> head = this; Queue<TreeNode<E>> queue = new ArrayDeque<>(); queue.offer(head); while (!queue.isEmpty()) { for (int i = 0; i < queue.size(); i++) { level++; TreeNode<E> tmp = queue.poll(); if (tmp.left == null && tmp.right == null) { return level; } if (tmp.left != null) { queue.offer(tmp.left); } if (tmp.right != null) { queue.offer(tmp.right); } } } return 0; } // 遞歸求樹的最大和最小深度 public int minLevel(TreeNode head) { if (head == null) { return 0; } if (head.left == null && head.right == null) { return 1; } if (head.left == null && head.right != null) { return minLevel(head.left) + 1; } if (head.left != null && head.right == null) { return minLevel(head.right) + 1; } return Math.min(minLevel(head.left), minLevel(head.right)) + 1; }
// 遞歸求兩個結點的公共祖先,一個結點能夠是本身的祖先 public TreeNode ancestor(TreeNode root, TreeNode node1, TreeNode node2) { if (root == node1 || root == node2) { return root; } TreeNode left = ancestor(root.left, node1, node2); TreeNode right = ancestor(root.right, node1, node2); if (left == null || right == null) { return root; } return left != null ? left : right; }
天天用心記錄一點點。內容也許不重要,但習慣很重要!算法