Java實現二叉樹及相關遍歷方式
在計算機科學中,二叉樹是每個節點最多有兩個子樹的樹結構。通常子樹被稱作“左子樹”(left subtree)和“右子樹”(right subtree)。二叉樹常被用於實現二叉查找樹和二叉堆。以下用Java實現對二叉樹的先序遍歷,中序遍歷,後序遍歷,廣度優先遍歷,深度優先遍歷。轉摘請註明:http://blog.csdn.net/qiuzhping/article/details/44830369
package com.qiuzhping.tree;
import java.util.ArrayDeque;
import java.util.LinkedList;
import java.util.List;
/**
* 功能:把一個數組的值存入二叉樹中,然後進行3種方式的遍歷.
* 構造的二叉樹:
* 1
* / \
* 2 3
* / \ / \
* 4 5 6 7
* / \
* 8 9
* 先序遍歷:DLR
* 1 2 4 8 9 5 3 6 7
* 中序遍歷:LDR
* 8 4 9 2 5 1 6 3 7
* 後序遍歷:LRD
* 8 9 4 5 2 6 7 3 1
* 深度優先遍歷
* 1 2 4 8 9 5 3 6 7
* 廣度優先遍歷
* 1 2 3 4 5 6 7 8 9
* @author Peter.Qiu
* @version [Version NO, 2015年4月2日]
* @see [Related classes/methods]
* @since [product/module version]
*/
public class binaryTreeTest {
private int[] array = { 1, 2, 3, 4, 5, 6, 7, 8, 9 };
private static List<Node> nodeList = null;
/**
* 內部類:節點
*
*/
private static class Node {
Node leftChild;
Node rightChild;
int data;
Node(int newData) {
leftChild = null;
rightChild = null;
data = newData;
}
}
/** 二叉樹的每個結點至多隻有二棵子樹(不存在度大於2的結點),二叉樹的子樹有左右之分,次序不能顛倒。<BR>
* 二叉樹的第i層至多有2^{i-1}個結點;深度爲k的二叉樹至多有2^k-1個結點;<BR>
* 對任何一棵二叉樹T,如果其終端結點數爲n_0,度爲2的結點數爲n_2,則n_0=n_2+1。<BR>
*一棵深度爲k,且有2^k-1個節點稱之爲滿二叉樹;深度爲k,有n個節點的二叉樹,<BR>
*當且僅當其每一個節點都與深度爲k的滿二叉樹中,序號爲1至n的節點對應時,稱之爲完全二叉樹.<BR>
* @author Peter.Qiu [Parameters description]
* @return void [Return type description]
* @exception throws [Exception] [Exception description]
* @see [Related classes#Related methods#Related properties]
*/
public void createTree() {
nodeList = new LinkedList<Node>();
// 將一個數組的值依次轉換爲Node節點
for (int nodeIndex = 0; nodeIndex < array.length; nodeIndex++) {
nodeList.add(new Node(array[nodeIndex]));
}
// 對前lastParentIndex-1個父節點按照父節點與孩子節點的數字關係建立二叉樹
for (int parentIndex = 0; parentIndex < array.length / 2 - 1; parentIndex++) {
// 左孩子
nodeList.get(parentIndex).leftChild = nodeList
.get(parentIndex * 2 + 1);
// 右孩子
nodeList.get(parentIndex).rightChild = nodeList
.get(parentIndex * 2 + 2);
}
// 最後一個父節點:因爲最後一個父節點可能沒有右孩子,所以單獨拿出來處理
int lastParentIndex = array.length / 2 - 1;
// 左孩子
nodeList.get(lastParentIndex).leftChild = nodeList
.get(lastParentIndex * 2 + 1);
// 右孩子,如果數組的長度爲奇數才建立右孩子
if (array.length % 2 == 1) {
nodeList.get(lastParentIndex).rightChild = nodeList
.get(lastParentIndex * 2 + 2);
}
}
/**
* 先序遍歷
*
* 這三種不同的遍歷結構都是一樣的,只是先後順序不一樣而已
*
* @param node
* 遍歷的節點
*/
public void preOrderTraverse(Node node) {
if (node == null)
return;
System.out.print(node.data + " ");
preOrderTraverse(node.leftChild);
preOrderTraverse(node.rightChild);
}
/**
* 中序遍歷
*
* 這三種不同的遍歷結構都是一樣的,只是先後順序不一樣而已
*
* @param node
* 遍歷的節點
*/
public void inOrderTraverse(Node node) {
if (node == null)
return;
inOrderTraverse(node.leftChild);
System.out.print(node.data + " ");
inOrderTraverse(node.rightChild);
}
/**
* 後序遍歷
*
* 這三種不同的遍歷結構都是一樣的,只是先後順序不一樣而已
*
* @param node
* 遍歷的節點
*/
public void postOrderTraverse(Node node) {
if (node == null)
return;
postOrderTraverse(node.leftChild);
postOrderTraverse(node.rightChild);
System.out.print(node.data + " ");
}
/**
* 深度優先遍歷,相當於先根遍歷
* 採用非遞歸實現
* 需要輔助數據結構:棧
*/
public void depthOrderTraversal(Node root){
System.out.println("\n深度優先遍歷");
if(root==null){
System.out.println("empty tree");
return;
}
ArrayDeque<Node> stack=new ArrayDeque<Node>();
stack.push(root);
while(stack.isEmpty()==false){
Node node=stack.pop();
System.out.print(node.data+ " ");
if(node.rightChild!=null){
stack.push(node.rightChild);
}
if(node.leftChild!=null){
stack.push(node.leftChild);
}
}
System.out.print("\n");
}
/**
* 廣度優先遍歷
* 採用非遞歸實現
* 需要輔助數據結構:隊列
*/
public void levelOrderTraversal(Node root){
System.out.println("廣度優先遍歷");
if(root==null){
System.out.println("empty tree");
return;
}
ArrayDeque<Node> queue=new ArrayDeque<Node>();
queue.add(root);
while(queue.isEmpty()==false){
Node node=queue.remove();
System.out.print(node.data+ " ");
if(node.leftChild!=null){
queue.add(node.leftChild);
}
if(node.rightChild!=null){
queue.add(node.rightChild);
}
}
System.out.print("\n");
}
/**
*構造的二叉樹:
* 1
* / \
* 2 3
* / \ / \
* 4 5 6 7
* / \
* 8 9
* 先序遍歷:DLR
* 1 2 4 8 9 5 3 6 7
* 中序遍歷:LDR
* 8 4 9 2 5 1 6 3 7
* 後序遍歷:LRD
* 8 9 4 5 2 6 7 3 1
* 深度優先遍歷
* 1 2 4 8 9 5 3 6 7
* 廣度優先遍歷
* 1 2 3 4 5 6 7 8 9
*/
public static void main(String[] args) {
BinaryTreeTest binTree = new BinaryTreeTest();
binTree.createTree();
// nodeList中第0個索引處的值即爲根節點
Node root = nodeList.get(0);
System.out.println("先序遍歷:");
binTree.preOrderTraverse(root);
System.out.println();
System.out.println("中序遍歷:");//LDR
binTree.inOrderTraverse(root);
System.out.println();
System.out.println("後序遍歷:");//LRD
binTree.postOrderTraverse(root);
binTree.depthOrderTraversal(root);//深度遍歷
binTree.levelOrderTraversal(root);//廣度遍歷
}
}