二叉樹是很常用的一種數據結構。但是在使用它之前,得先構造一棵二叉樹,下面這篇文章記錄一下如何構造一棵二叉排序樹 和 完全二叉樹。
一,給定一組整數,請構造一棵二叉排序樹
比如:2,4,5,1,3
構造二叉排序樹,采用了遞歸方式來構造。
1 //根據數組 arr 中的元素構造一棵二叉排序樹 2 public void buildTree(int[] arr){ 3 for (int node : arr) { 4 insert(node); 5 } 6 } 7 8 private void insert(int ele){ 9 root = insert(root, ele); 10 } 11 12 private BinaryNode insert(BinaryNode root, int ele){ 13 //遞歸的結束條件.base condition 14 if(root == null) 15 return new BinaryNode(ele); 16 17 if(root.ele > ele) 18 root.left = insert(root.left, ele); 19 else if(root.ele < ele) 20 root.right = insert(root.right, ele); 21 else 22 root.left = insert(root.left, ele); 23 24 return root;//若某結點的左右孩子不空,在后續的遞歸調用中該結點的左右指針是不會變的. 25 }
二,給定一組整數,請按照從上到下,從左到右的順序構造一棵二叉樹(其實就是完全二叉樹)
比如:2,4,5,1,3
構造一棵完全二叉樹,其實這個過程與“二叉樹的按層打印非常相似”。因此,需要一個隊列保存“下一個待構造的結點”。
當某個結點的左右孩子都已經構造完畢時(next==2),從隊列中取出下一個結點,並開始構造它的左右孩子。
1 public void buildCompleteTree(int[] nodes){ 2 Queue<BinaryNode> queue = new LinkedList<BinaryNode>(); 3 root = new BinaryNode(nodes[0]); 4 BinaryNode currentNode = null; 5 6 // queue.offer(root); 7 int next = 0;//標記當前結點的左右孩子是否已經構造完畢,當next為2時表示當前結點的左右孩子已經構造完畢 8 currentNode = root;//保存當前正在"構造"的結點 9 int count = 1;//記錄數組中的已經構造的元素 10 while(count < nodes.length){ 11 if(next == 2)//某結點的左右孩子已經構造好了,該結點才能夠 出隊列 12 { 13 currentNode = queue.poll(); 14 next = 0; 15 } 16 if(currentNode.left == null && count < nodes.length)//完全二叉樹,先構造左孩子 17 { 18 currentNode.left = new BinaryNode(nodes[count++]); 19 queue.offer(currentNode.left); 20 next++; 21 } 22 if(currentNode.right == null && count < nodes.length)//再構造右孩子 23 { 24 currentNode.right = new BinaryNode(nodes[count++]); 25 queue.offer(currentNode.right); 26 next++; 27 } 28 } 29 }
三,完整代碼實現

import java.util.LinkedList; import java.util.Queue; public class MyBinarySearchTree { private class BinaryNode{ BinaryNode left; BinaryNode right; int ele; public BinaryNode(int ele) { this.ele = ele; } } private BinaryNode root;//根節點 //根據數組 arr 中的元素構造一棵二叉排序樹 public void buildTree(int[] arr){ for (int node : arr) { insert(node); } } private void insert(int ele){ root = insert(root, ele); } private BinaryNode insert(BinaryNode root, int ele){ //遞歸的結束條件.base condition if(root == null) return new BinaryNode(ele); if(root.ele > ele) root.left = insert(root.left, ele); else if(root.ele < ele) root.right = insert(root.right, ele); else root.left = insert(root.left, ele); return root;//若某結點的左右孩子不空,在后續的遞歸調用中該結點的左右指針是不會變的. } public void printTreeLineByLine(BinaryNode root){ Queue<BinaryNode> queue = new LinkedList<MyBinarySearchTree.BinaryNode>(); int current = 1;//當前層未打印的結點個數 int next = 0;//下一層待打印的結點個數 queue.offer(root); BinaryNode currentNode; while(!queue.isEmpty()) { currentNode = queue.poll(); current--; System.out.print(currentNode.ele + " ");//打印當前節點 if(currentNode.left != null) { queue.offer(currentNode.left); next++; } if(currentNode.right != null) { queue.offer(currentNode.right); next++; } if(current == 0)//表示本行所有的結點已經打印完了 { System.out.println();//打印下一行 current = next; next = 0; } } } public void buildCompleteTree(int[] nodes){ Queue<BinaryNode> queue = new LinkedList<BinaryNode>(); root = new BinaryNode(nodes[0]); BinaryNode currentNode = null; // queue.offer(root); int next = 0;//標記當前結點的左右孩子是否已經構造完畢 currentNode = root;//保存當前正在"構造"的結點 int count = 1;//記錄數組中的已經構造的元素 while(count < nodes.length){ if(next == 2)//某結點的左右孩子已經構造好了 { currentNode = queue.poll(); next = 0; } if(currentNode.left == null && count < nodes.length) { currentNode.left = new BinaryNode(nodes[count++]); queue.offer(currentNode.left); next++; } if(currentNode.right == null && count < nodes.length) { currentNode.right = new BinaryNode(nodes[count++]); queue.offer(currentNode.right); next++; } } } //test public static void main(String[] args) { MyBinarySearchTree bst = new MyBinarySearchTree(); int[] arr = {2,4,5,1,3}; // bst.buildTree(arr); // bst.printTreeLineByLine(bst.root); System.out.println("----------------"); bst.buildCompleteTree(arr); bst.printTreeLineByLine(bst.root); } }
原文地址:博客園hapjin http://www.cnblogs.com/hapjin/p/5738354.html