1. 程式人生 > >二叉樹三種遍歷方式及通過兩種遍歷重構二叉樹(java實現)

二叉樹三種遍歷方式及通過兩種遍歷重構二叉樹(java實現)

重構方法參考文章【重構二叉樹(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);
	}
}