二叉樹三種遍歷方式及通過兩種遍歷重構二叉樹(java實現)
阿新 • • 發佈:2018-12-22
重構方法參考文章【重構二叉樹(Java實現):https://blog.csdn.net/wangbingcsu/article/details/51372695】
文章目錄
- 二叉樹類
- 三種遍歷方式
- 前序遍歷
- 中序遍歷
- 後序遍歷
- 兩種重構方式
- 通過前序遍歷中序遍歷重構二叉樹
- 通過後序遍歷中序遍歷重構二叉樹
- 總程式碼
- 測試程式碼
二叉樹類
這裡我們建立一個二叉樹的類,併為他新增一個插入的方法(左節點總是比父節點小,右節點總是比父節點大)
public class BinaryTree { int data; BinaryTree left; BinaryTree right; public BinaryTree(int data) { this.data = data; left = null; right = null; } public void insert(BinaryTree root, int data) {//左節點總是比父節點小,右節點總是比父節點大 if (data > root.data) { if (root.right == null) { root.right = new BinaryTree(data); } else { this.insert(root.right, data); } } else { if (root.left == null) { root.left = new BinaryTree(data); } else { this.insert(root.left, data); } } } }
三種遍歷方式
這三種遍歷方式,相對的是根節點的遍歷順序。
前序遍歷
1.訪問根節點
2.前序遍歷左子樹
3.前序遍歷右子樹
public static void preOrder(BinaryTree root) {//前序遍歷
if (root != null) {
System.out.print(root.data + ",");// 資料在同一行輸出
preOrder(root.left);
preOrder(root.right);
}
}
中序遍歷
1.中序遍歷左子樹
2.訪問根節點
3.中序遍歷右子樹
public static void inOrder(BinaryTree root) {//中序遍歷
if (root != null) {
inOrder(root.left);
System.out.print(root.data + ",");// 資料在同一行輸出
inOrder(root.right);
}
}
後序遍歷
1.後序遍歷左子樹
2.後序遍歷右子樹
3.訪問根節點
public static void postOrder(BinaryTree root) {//後序遍歷 if (root != null) { postOrder(root.left); postOrder(root.right); System.out.print(root.data + ",");// 資料在同一行輸出 } }
兩種重構方式
我們可以通過前序遍歷和中序遍歷重構出唯一的二叉樹,也可以通過中序遍歷和後序遍歷重構出唯一的二叉樹,
但是通過前序遍歷和後序遍,無法重構出唯一的二叉樹。
通過前序遍歷中序遍歷重構二叉樹
- 值確定根節點:根據前序遍歷的第一個值確定根節點
- 遞迴確定左子樹
- 遞迴確定右子樹
// 根據前序中序重構二叉樹
public static BinaryTree reConstructBinaryTree1(int[] pre, int[] in) {
if (0 == pre.length || 0 == in.length)
return null;
// 先序遍歷陣列的第一個元素作為根節點
BinaryTree root = new BinaryTree(pre[0]);
for (int i = 0; i < in.length; ++i) {
if (root.data == in[i]) {
root.left = reConstructBinaryTree1(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree1(Arrays.copyOfRange(pre, i + 1, pre.length),
Arrays.copyOfRange(in, i + 1, in.length));
}
}
return root;
}
通過後序遍歷中序遍歷重構二叉樹
- 值確定根節點:根據後序遍歷的最後一個值確定根節點
- 遞迴確定左子樹
- 遞迴確定右子樹
// 根據後序中序重構二叉樹
public static BinaryTree reConstructBinaryTree2(int[] post, int[] in) {
if (0 == post.length || 0 == in.length)
return null;
BinaryTree root = new BinaryTree(post[post.length - 1]);
for (int i = 0; i < in.length; ++i) {
if (root.data == in[i]) {
root.left = reConstructBinaryTree2(Arrays.copyOfRange(post, 0, i), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree2(Arrays.copyOfRange(post, i, post.length - 1),
Arrays.copyOfRange(in, i + 1, in.length));
}
}
return root;
}
總程式碼
這裡,為了省事,把二叉樹三種遍歷方式和兩種重構方式都寫在了這個類裡。
public class BinaryTree {
int data;
BinaryTree left;
BinaryTree right;
public BinaryTree(int data) {
this.data = data;
left = null;
right = null;
}
public void insert(BinaryTree root, int data) {// 左節點總是比父節點小,右節點總是比父節點大
if (data > root.data) {
if (root.right == null) {
root.right = new BinaryTree(data);
} else {
this.insert(root.right, data);
}
} else {
if (root.left == null) {
root.left = new BinaryTree(data);
} else {
this.insert(root.left, data);
}
}
}
public static BinaryTree reConstructBinaryTree(int[] pre, int[] in) {// 根據前序中序重構二叉樹
if (pre.length == 0 || in.length == 0) {
return null;
}
BinaryTree node = new BinaryTree(pre[0]);
for (int i = 0; i < in.length; i++) {
if (pre[0] == in[i]) {
node.left = reConstructBinaryTree(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
node.right = reConstructBinaryTree(Arrays.copyOfRange(pre, i + 1, pre.length),
Arrays.copyOfRange(in, i + 1, in.length));
}
}
return node;
}
// 根據前序中序重構二叉樹
public static BinaryTree reConstructBinaryTree1(int[] pre, int[] in) {
if (0 == pre.length || 0 == in.length)
return null;
// 先序遍歷陣列的第一個元素作為根節點
BinaryTree root = new BinaryTree(pre[0]);
for (int i = 0; i < in.length; ++i) {
if (root.data == in[i]) {
root.left = reConstructBinaryTree1(Arrays.copyOfRange(pre, 1, i + 1), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree1(Arrays.copyOfRange(pre, i + 1, pre.length),
Arrays.copyOfRange(in, i + 1, in.length));
}
}
return root;
}
public static BinaryTree reConstructBinaryTree2(int[] post, int[] in) {// 根據後序中序重構二叉樹
if (0 == post.length || 0 == in.length)
return null;
BinaryTree root = new BinaryTree(post[post.length - 1]);
for (int i = 0; i < in.length; ++i) {
if (root.data == in[i]) {
root.left = reConstructBinaryTree2(Arrays.copyOfRange(post, 0, i), Arrays.copyOfRange(in, 0, i));
root.right = reConstructBinaryTree2(Arrays.copyOfRange(post, i, post.length - 1),
Arrays.copyOfRange(in, i + 1, in.length));
}
}
return root;
}
// 三種遍歷方式
public static void preOrder(BinaryTree root) {// 前序遍歷
if (root != null) {
System.out.print(root.data + ",");// 資料在同一行輸出
preOrder(root.left);
preOrder(root.right);
}
}
public static void inOrder(BinaryTree root) {// 中序遍歷
if (root != null) {
inOrder(root.left);
System.out.print(root.data + ",");// 資料在同一行輸出
inOrder(root.right);
}
}
public static void postOrder(BinaryTree root) {// 後序遍歷
if (root != null) {
postOrder(root.left);
postOrder(root.right);
System.out.print(root.data + ",");// 資料在同一行輸出
}
}
}
測試
這裡為了省事,測試類直接繼承二叉樹類,進行測試。
public class BinaryTreeTest extends BinaryTree {
public BinaryTreeTest(int data) {
super(data);
}
public static void main(String[] args) {
testReConstruct();
}
public static void testReConstruct() {// 測試重構二叉樹
int[] pre = { 12, 9, 76, 35, 22, 16, 48, 46, 40, 90 };
int[] in = { 9, 12, 16, 22, 35, 40, 46, 48, 76, 90 };
int[] post = { 9, 16, 22, 40, 46, 48, 35, 90, 76, 12, };
BinaryTree root = reConstructBinaryTree2(post, in);
postOrder(root);
}
public static void testOrder() {// 測試三種遍歷
int[] list = { 12, 76, 35, 22, 16, 48, 90, 46, 9, 40 };
BinaryTree root = new BinaryTree(list[0]);
for (int i = 1; i < list.length; i++) {
root.insert(root, list[i]);
}
preOrder(root);
System.out.println();// 換行
inOrder(root);
System.out.println();// 換行
postOrder(root);
}
}