二叉樹相關演算法——建立、遍歷、求深度和廣度
阿新 • • 發佈:2019-02-07
二叉樹相關的演算法,遍歷使用了遞迴和迭代兩種演算法,可作為結果對比。
理解起來不難,直接上程式碼,有空再補下注釋說明原理。
package com.junyang.algodemo.Tree;
import java.util.LinkedList;
import java.util.Stack;
public class TreeUtil {
private static final int DEEP = 5;
/* 建立一個深度為deep的滿二叉樹,目的是為驗證其它演算法 */
public static TreeNode createTree(int deep) {
/* 處理deep為0 和為1的特殊情況 */
if (0 >= deep) {
return null;
}
int count = 0;
TreeNode root = new TreeNode(count++);
if (1 == deep) {
return root;
}
/* 滿二叉樹建立完成的條件為,當前這一層達到2的 deep-1 次方 */
double maxLayerNum = Math.pow(2f, deep - 1f);
TreeNode last = root;
/* 通過佇列按層建立二叉樹 */
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
int width = 0;
while (!queue.isEmpty()) {
TreeNode temp = queue.remove();
temp.left = new TreeNode(count++);
temp.right = new TreeNode(count++);
queue.add(temp.left);
queue.add(temp.right);
width += 2 ;
if (width == maxLayerNum) {
return root;
}
if (temp == last) {
last = last.right;
width = 0;
}
}
return root;
}
/* 按層遍歷同時按行顯示 */
public static void printTreeForLayer(TreeNode root) {
if (null == root) {
return;
}
LinkedList<TreeNode> queue = new LinkedList<>();
queue.add(root);
TreeNode last = root;
TreeNode nlast = root;
int lineNum = 1;
System.out.print("num[" + lineNum++ + "]:");
while (!queue.isEmpty()) {
TreeNode temp = queue.remove();
if (null != temp.left) {
queue.add(temp.left);
nlast = temp.left;
}
if (null != temp.right) {
queue.add(temp.right);
nlast = temp.right;
}
System.out.print(temp.data + " ");
if (temp == last) {
System.out.println();
if (!queue.isEmpty()) {
System.out.print("num[" + lineNum++ + "]:");
}
last = nlast;
}
}
}
/* 先序遍歷 —— 遞迴 */
public static void printTreeForRootFirst1(TreeNode root) {
if (root == null) {
return;
}
System.out.print(root.data + " ");
printTreeForRootFirst1(root.left);
printTreeForRootFirst1(root.right);
}
/* 先序遍歷 —— 迭代*/
public static void printTreeForRootFirst2(TreeNode root) {
if (null == root) {
return;
}
Stack<TreeNode> stack = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode top = stack.pop();
System.out.print(top.data + " ");
if (top.right != null) {
stack.push(top.right);
}
if (top.left != null) {
stack.push(top.left);
}
}
}
/* 中序遍歷 —— 遞迴 */
public static void printTreeForRootMiddle(TreeNode root) {
if (root == null) {
return;
}
printTreeForRootMiddle(root.left);
System.out.print(root.data + " ");
printTreeForRootMiddle(root.right);
}
/* 中序遍歷 —— 迭代 */
public static void printTreeForRootMiddle2(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
TreeNode cur = root;
while (!stack.isEmpty() || cur != null) {
if (cur != null) {
stack.push(cur);
cur = cur.left;
} else {
cur = stack.pop();
System.out.print(cur.data + " ");
cur = cur.right;
}
}
}
/* 後序遍歷 —— 遞迴 */
public static void printTreeForRootLast(TreeNode root) {
if (root == null) {
return;
}
printTreeForRootLast(root.left);
printTreeForRootLast(root.right);
System.out.print(root.data + " ");
}
/* 後序遍歷 —— 迭代 */
public static void printTreeForRootLast2(TreeNode root) {
if (root == null) {
return;
}
Stack<TreeNode> stack = new Stack<>();
Stack<TreeNode> output = new Stack<>();
stack.push(root);
while (!stack.isEmpty()) {
TreeNode temp = stack.pop();
output.push(temp);
if (null != temp.left) {
stack.push(temp.left);
}
if (null != temp.right) {
stack.push(temp.right);
}
}
while (!output.isEmpty()) {
System.out.print(output.pop().data + " ");
}
}
/* 獲取二叉樹的寬度 */
public static int getWidth(TreeNode root) {
if (null == root) {
return 0;
}
int maxWidth = 1;
int curWidth = 0;
LinkedList<TreeNode> linkedList = new LinkedList<>();
linkedList.add(root);
TreeNode last = root;
TreeNode nlast = root;
while (!linkedList.isEmpty()) {
TreeNode temp = linkedList.remove();
if (null != temp.left) {
linkedList.add(temp.left);
nlast = temp.left;
curWidth++;
}
if (null != temp.right) {
linkedList.add(temp.right);
nlast = temp.right;
curWidth++;
}
if (temp == last) {
last = nlast;
maxWidth = maxWidth > curWidth ? maxWidth : curWidth;
curWidth = 0;
}
}
return maxWidth;
}
/* 獲取二叉樹的深度 */
public static int getDeep(TreeNode root) {
if (null == root) {
return 0;
}
int leftDeep = 0;
if (root.left != null) {
leftDeep = getDeep(root.left);
}
int rightDeep = 0;
if (root.right != null) {
rightDeep = getDeep(root.right);
}
return (rightDeep > leftDeep ? rightDeep : leftDeep) + 1;
}
public static void main(String[] args) {
TreeNode root = createTree(DEEP);
System.out.println("按層遍歷");
printTreeForLayer(root);
System.out.println("先序遍歷");
printTreeForRootFirst1(root);
System.out.println();
printTreeForRootFirst2(root);
System.out.println();
System.out.println("中序遍歷");
printTreeForRootMiddle(root);
System.out.println();
printTreeForRootMiddle2(root);
System.out.println();
System.out.println("後序遍歷");
printTreeForRootLast(root);
System.out.println();
printTreeForRootLast2(root);
System.out.println();
System.out.println("deep:" + getDeep(root));
System.out.println("width:" + getWidth(root));
}
}
輸出:
按層遍歷
num[1]:0
num[2]:1 2
num[3]:3 4 5 6
num[4]:7 8 9 10 11 12 13 14
num[5]:15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30
先序遍歷
0 1 3 7 15 16 8 17 18 4 9 19 20 10 21 22 2 5 11 23 24 12 25 26 6 13 27 28 14 29 30
0 1 3 7 15 16 8 17 18 4 9 19 20 10 21 22 2 5 11 23 24 12 25 26 6 13 27 28 14 29 30
中序遍歷
15 7 16 3 17 8 18 1 19 9 20 4 21 10 22 0 23 11 24 5 25 12 26 2 27 13 28 6 29 14 30
15 7 16 3 17 8 18 1 19 9 20 4 21 10 22 0 23 11 24 5 25 12 26 2 27 13 28 6 29 14 30
後序遍歷
15 16 7 17 18 8 3 19 20 9 21 22 10 4 1 23 24 11 25 26 12 5 27 28 13 29 30 14 6 2 0
15 16 7 17 18 8 3 19 20 9 21 22 10 4 1 23 24 11 25 26 12 5 27 28 13 29 30 14 6 2 0
deep:5
width:16