構造二叉樹&4種遍歷方法
目的:通過一個任意數組(可以包含Null,而且空的節點沒必要全部用Null值填充)來構造一個任意形式的二叉樹(可以是完全二叉樹,也可以是非完全二叉樹)。
看網上好多教程由數組構造二叉樹都是“完全二叉樹”,即使可以產生非完全二叉樹也必須將空節點全部用Null表示填入數組中(這樣其實就跟完全二叉樹等效了)。這裏用Python2和Java兩種語言實現了通過任意數組構造任意二叉樹。
這樣便可以模仿leetcode平臺在自己的IDE中進行關於二叉樹題目的debug了。
另外,實現四種遍歷方式(前序、中序、後序遍歷,以及層次遍歷),以print構造的二叉樹。
1. Python2實現
# 創建二叉樹。 從含有None的數組創建非完全二叉樹 !!!
# 將list換成隊列queue,pop(0)更方便。
def creatTree(self, nums):
if not nums:
return None
root = TreeNode(nums[0])
nums.remove(nums[0])
lst = [root]
while(lst and nums):
tmp = lst[0]
lst.remove(lst[0])
if tmp:
left = nums[0]
tmp.left = TreeNode(left) if left else None
nums.remove(nums[0])
lst.append(tmp.left)
try:
right = nums[0]
tmp.right = TreeNode(right) if right else None
nums.remove(nums[0])
lst.append(tmp.right)
except:
pass
return root
這裏其實使用queue更方便,從尾部push頭部pop。
下邊Python的遍歷只寫兩種,前序和層次。
# 先序遍歷
def preorder(self, root):
"""遞歸實現先序遍歷"""
if root == None:
return
print(root.val),
self.preorder(root.left)
self.preorder(root.right)
# 層次遍歷
def levelOrder(self, root):
if not root:
return None
queue = list()
# queue = []
queue.append(root)
while(queue):
node = queue.pop(0)
print node.val,
if node.left:
queue.append(node.left)
if node.right:
queue.append(node.right)
2. Java實現
package leetcode.easy;
import java.util.LinkedList;
import java.util.Queue;
class TreeNode {
int val;
TreeNode left;
TreeNode right;
TreeNode(int x) { val = x; }
}
public class CreatBinaryTree {
// 遞歸法構建完全二叉樹,不是完全二叉樹的話葉構建不出來。
public static TreeNode createCompleteBT(Integer[] arr, int i) // 初始時,傳入的i==0
{
TreeNode root = null; // 定義根節點
if (i >= arr.length) // i >= arr.length 時,表示已經到達了根節點
return null;
// System.out.println(arr[i]);
if (arr[i] == null) { // 是null的話直接return,否則下面TreeNode(arr[i])會error。
return null;
}
root = new TreeNode(arr[i]); // 根節點
root.left = createCompleteBT(arr, 2*i+1); // 遞歸建立左孩子結點
root.right = createCompleteBT(arr, 2*i+2); // 遞歸建立右孩子結點
return root;
}
// 創建二叉樹,從含有None的數組創建非完全二叉樹 !!!
// 將list換成隊列queue,pop(0)更方便。
public static TreeNode creatAnyBiTreeByArr(Integer[] arr){
Queue<Integer> queue_num = new LinkedList<Integer>();
for(int i=0;i<arr.length;i++){
queue_num.add(arr[i]);
// ((LinkedList<Integer>) q1).add(null);
}
if (queue_num.isEmpty()) return null;
TreeNode root = new TreeNode(queue_num.poll()); // poll() 方法在用空集合調用時不是拋出異常,只是返回 null !!
Queue<TreeNode> que_node = new LinkedList<TreeNode>();
que_node.offer(root);
while (!que_node.isEmpty() && !queue_num.isEmpty()){
TreeNode tmp = que_node.poll();
if(tmp != null){
Integer left = queue_num.poll();
Integer right = queue_num.poll();
if(left != null)
tmp.left = new TreeNode(left);
else tmp.left = null;
que_node.offer(tmp.left);
if(right != null)
tmp.right = new TreeNode(right);
else tmp.right = null;
que_node.offer(tmp.right);
}
}
return root;
}
// 先序遍歷
public static void preOrder(TreeNode root)
{
if (root == null)
return;
System.out.print(root.val+" ");
preOrder(root.left);
preOrder(root.right);
}
// 中序遍歷
public static void inOrder(TreeNode root)
{
if (root == null)
return;
inOrder(root.left);
System.out.print(root.val+" ");
inOrder(root.right);
}
// 後序遍歷
public static void postOrder(TreeNode root)
{
if (root == null)
return;
postOrder(root.left);
postOrder(root.right);
System.out.print(root.val+" ");
}
// 層次遍歷
public static void levelOrder(TreeNode root)
{
if (root == null){
return;
}
//add()和remove()方法在失敗的時候會拋出異常(不推薦)
Queue<TreeNode> queue = new LinkedList<TreeNode>();
queue.offer(root);
while (! queue.isEmpty()) {
TreeNode node = queue.poll();
System.out.print(node.val+" ");
if (node.left != null){
queue.offer(node.left);
}
if (node.right != null){
queue.offer(node.right);
}
}
}
// ########## test ##########
public static void main(String[] args) {
CreatBinaryTree sl = new CreatBinaryTree();
// *************** ...
Integer[] data1 = new Integer[] {0,1,2,null,3,4,null,5};
Integer[] data3 = new Integer[] {0,1,null,2,null,3};
TreeNode root1 = createCompleteBT(data1,0);
TreeNode root2 = creatAnyBiTreeByArr(data1);
// 構建任意二叉樹
TreeNode root3 = sl.creatAnyBiTreeByArr(data3);
levelOrder(root1); // 0 1 2 3 4
System.out.println();
preOrder(root1); // 0 1 3 2 4
System.out.println();
preOrder(root2); // 0 1 3 5 2 4
System.out.println();
sl.levelOrder(root3); // 0 1 2 3
System.out.println();
sl.preOrder(root3); // 0 1 2 3
}
}
對比root1和root2的結果,同樣的數組,不同的樹結構,因爲前者只能構造“完全二叉樹”或者由Null值填充空位的僞完全二叉樹(如將data1填充成爲[0,1,2,null,3,4,null,null,null,5], 便可以通過createCompleteBT 函數構造與後者creatAnyBiTreeByArr相同的形式了)。
3. 樹結構可視化
如數組[0, 1, null, 2, null, 3] 通過creatAnyBiTreeByArr函數構造出來的數的形式如下圖,這裏不需要把此數組填充成爲[0, 1, null, 2, null, null, null, 3].