Java實現二叉樹及相關遍歷方式

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);//廣度遍歷
	}

}




發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章