java中樹的遍歷,包括先序遍歷、中序遍歷、後序遍歷以及廣度優先遍歷跟深度優先遍歷
阿新 • • 發佈:2018-11-11
先總結一下各種遍歷方式的區別
前序遍歷:根結點 ---> 左子樹 ---> 右子樹
中序遍歷:左子樹---> 根結點 ---> 右子樹
後序遍歷:左子樹 ---> 右子樹 ---> 根結點
廣度優先,從左到右
深度優先,從上至下
程式碼:
package com.ietree.basic.datastructure.tree.binarytree; import java.util.*; public class ThreeLinkBinTree<E> { public static class TreeNode { Object data; TreeNode left; TreeNode right; TreeNode parent; public TreeNode() { } public TreeNode(Object data) { this.data = data; } public TreeNode(Object data, TreeNode left, TreeNode right, TreeNode parent) { this.data = data; this.left = left; this.right = right; this.parent = parent; } } private TreeNode root; /** * 以預設的構造器建立二叉樹 */ public ThreeLinkBinTree() { this.root = new TreeNode(); } /** * 以指定根元素建立二叉樹 */ public ThreeLinkBinTree(E data) { this.root = new TreeNode(data); } /** * 為指定節點新增子節點 * * @param parent 需要新增子節點的父節點的索引 * @param data 新子節點的資料 * @param isLeft 是否為左節點 * @return 新增的節點 */ public TreeNode addNode(TreeNode parent, E data, boolean isLeft) { if (parent == null) { throw new RuntimeException(parent + "節點為null, 無法新增子節點"); } if (isLeft && parent.left != null) { throw new RuntimeException(parent + "節點已有左子節點,無法新增左子節點"); } if (!isLeft && parent.right != null) { throw new RuntimeException(parent + "節點已有右子節點,無法新增右子節點"); } TreeNode newNode = new TreeNode(data); if (isLeft) { // 讓父節點的left引用指向新節點 parent.left = newNode; } else { // 讓父節點的left引用指向新節點 parent.right = newNode; } // 讓新節點的parent引用到parent節點 newNode.parent = parent; return newNode; } /** * 判斷二叉樹是否為空 */ public boolean empty() { // 根據元素判斷二叉樹是否為空 return root.data == null; } // 返回根節點 public TreeNode root() { if (empty()) { throw new RuntimeException("樹為空,無法訪問根節點"); } return root; } // 返回指定節點(非根節點)的父節點 public E parent(TreeNode node) { if (node == null) { throw new RuntimeException("節點為null,無法訪問其父節點"); } return (E) node.parent.data; } // 返回指定節點(非葉子)的左子節點,當左子節點不存在時返回null public E leftChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點為null,無法新增子節點"); } return parent.left == null ? null : (E) parent.left.data; } // 返回指定節點(非葉子)的右子節點,當右子節點不存在時返回null public E rightChild(TreeNode parent) { if (parent == null) { throw new RuntimeException(parent + "節點為null,無法新增子節點"); } return parent.right == null ? null : (E) parent.right.data; } // 返回該二叉樹的深度 public int deep() { // 獲取該樹的深度 return deep(root); } // 這是一個遞迴方法:每一棵子樹的深度為其所有子樹的最大深度 + 1 private int deep(TreeNode node) { if (node == null) { return 0; } // 沒有子樹 if (node.left == null && node.right == null) { return 1; } else { int leftDeep = deep(node.left); int rightDeep = deep(node.right); // 記錄其所有左、右子樹中較大的深度 int max = leftDeep > rightDeep ? leftDeep : rightDeep; // 返回其左右子樹中較大的深度 + 1 return max + 1; } } // 實現先序遍歷 // 1、訪問根節點 // 2、遞迴遍歷左子樹 // 3、遞迴遍歷右子樹 public List<TreeNode> preIterator() { return preIterator(root); } private List<TreeNode> preIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); // 處理根節點 list.add(node); // 遞迴處理左子樹 if (node.left != null) { list.addAll(preIterator(node.left)); } // 遞迴處理右子樹 if (node.right != null) { list.addAll(preIterator(node.right)); } return list; } // 實現中序遍歷 // 1、遞迴遍歷左子樹 // 2、訪問根節點 // 3、遞迴遍歷右子樹 public List<TreeNode> inIterator() { return inIterator(root); } private List<TreeNode> inIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); // 遞迴處理左子樹 if (node.left != null) { list.addAll(inIterator(node.left)); } // 處理根節點 list.add(node); // 遞迴處理右子樹 if (node.right != null) { list.addAll(inIterator(node.right)); } return list; } // 實現後序遍歷 // 1、遞迴遍歷左子樹 // 2、遞迴遍歷右子樹 // 3、訪問根節點 public List<TreeNode> postIterator() { return postIterator(root); } private List<TreeNode> postIterator(TreeNode node) { List<TreeNode> list = new ArrayList<TreeNode>(); // 遞迴處理左子樹 if (node.left != null) { list.addAll(postIterator(node.left)); } // 遞迴處理右子樹 if (node.right != null) { list.addAll(postIterator(node.right)); } // 處理根節點 list.add(node); return list; } /** * 實現廣度優先遍歷 * 廣度優先遍歷又稱為按層遍歷,整個遍歷演算法先遍歷二叉樹的第一層(根節點),再遍歷根節點的兩個子節點(第二層),以此類推 */ public List<TreeNode> bFS() { Queue<TreeNode> queue = new ArrayDeque<TreeNode>(); List<TreeNode> list = new ArrayList<TreeNode>(); if (root != null) { // 將根元素加入“佇列” queue.offer(root); } while (!queue.isEmpty()) { // 將該佇列的“隊尾”的元素新增到List中 list.add(queue.peek()); TreeNode p = queue.poll(); // 如果左子節點不為null,將它加入“佇列” if (p.left != null) { queue.offer(p.left); } // 如果右子節點不為null,將它加入“佇列” if (p.right != null) { queue.offer(p.right); } } return list; } /** * 深度遍歷 * * @return */ public ArrayList<TreeNode> dFS() { ArrayList<TreeNode> lists = new ArrayList<TreeNode>(); Stack<TreeNode> stack = new Stack(); if (root == null) { return lists; } stack.push(root); while (!stack.isEmpty()) { TreeNode tree = stack.pop(); //先往棧中壓入右節點,再壓左節點,這樣出棧就是先左節點後右節點了。 if (tree.right != null) { stack.push(tree.right); } if (tree.left != null) { stack.push(tree.left); } lists.add(tree); } return lists; } }