Java實現二叉樹


二叉樹(Binary Tree):二叉樹是一棵樹,其中每個結點都不能有多於兩個的子結點;


特點:

     (1) 每個結點最多有兩棵子樹,沒有子樹或者只有一棵子樹也是可以的;

      (2)左子樹和右子樹是有順序的,次序不能任意顛倒;

      (3)即使樹中只有一棵子樹,也要區分它是左子樹還是右子樹;


特殊的二叉樹:

      (1)斜樹:顧名思義,斜樹一定是要斜的;所有的結點都只有左子樹的二叉樹叫左斜樹,所有的結點都只有右子樹的二叉樹叫右斜樹;其實,線性表就可以理解爲樹的一種特殊的表現形式;

       (2)滿二叉樹:在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且所有葉子都在同一層上,這樣的二叉樹稱爲滿二叉樹;如圖:

         (3)完全二叉樹:對一棵具有n個結點的二叉樹按層序編號,如果編號爲i的結點與同樣深度的滿二叉樹中編號爲i的結點在二叉樹中位置完全相同,那麼這棵二叉樹稱爲完全二叉樹;或者這樣理解:在一棵二叉樹中,除最後一層外,若其餘層都是滿的,並且最後一層或者是滿的,或者是右邊缺少連續若干個結點,則稱此樹爲完全二叉樹;

所以我們可以這樣判斷完全二叉樹:那就是看着樹的示意圖,心中默默給每個結點按照滿二叉樹的結構逐層順序編號,如果編號出現空檔,就說明不是完全二叉樹,否則就是;


二叉樹的實現:同樣,二叉樹也可以通過順序存儲和鏈式存儲來實現;

          二叉樹的順序存儲就是用一維數組存儲二叉樹中的結點,並且結點的存儲位置,也就是數組的下標要能體現結點之間的邏輯關係,比如父結點與子結點的邏輯關係,子結點 與子結點之間的關係;但順序存儲的實用性不強;

          所以一般採用鏈式存儲;


二叉樹的遍歷:是指從根結點出發,按照某種次序,依次訪問二叉樹中所有結點,使得每個結點被訪問一次且僅被訪問一次;

 二叉樹的遍歷方式有好多種,如果我們限制了從左到右的習慣方式,那麼主要就有以下幾種:

         (1)前序遍歷:先訪問子結點,然後前序遍歷左子樹,再前序遍歷右子樹;如下圖,遍歷順序是:ABDGHCEIF


         (2)中序遍歷:從根結點開始(但並不是先訪問根結點),中序遍歷根結點的左子樹,然後方式根結點,最後中序遍歷右樹,如圖,遍歷的順序是:GDHBAEICF

           (3)後序遍歷:從左到右先葉子後結點的方式遍歷訪問左右子樹,最後是訪問根結點;如圖,遍歷的順序是:GHDBIEFCA

          (4)層序遍歷:從樹的第一層,也就是根結點開始訪問,從上而下逐層遍歷,在同一層中,按從左到右的順序對結點進行逐個訪問;如圖,遍歷順序爲:ABCDEFGHI


代碼如下:

二叉樹結點

package binaryTree;

// 二叉樹節點 
public class BTNode
{
	private char key;                  // 數據
	private BTNode left, right;    // 左右子結點

	public BTNode(char key)
	{
		this(key, null, null);
	}

	public BTNode(char key, BTNode left, BTNode right)
	{
		this.key = key;
		this.left = left;
		this.right = right;
	}

	public char getKey()
	{
		return key;
	}

	public void setKey(char key)
	{
		this.key = key;
	}

	public BTNode getLeft()
	{
		return left;
	}

	public void setLeft(BTNode left)
	{
		this.left = left;
	}

	public BTNode getRight()
	{
		return right;
	}

	public void setRight(BTNode right)
	{
		this.right = right;
	}

}

二叉樹遍歷:

package binaryTree;

import java.util.Stack;

// 遍歷二叉樹 
public class BinTree
{
	protected BTNode root;

	public BinTree(BTNode root)
	{
		this.root = root;
	}

	public BTNode getRoot()
	{
		return root;
	}

	// 初始化,構造二叉樹
	public static BTNode init()
	{
		BTNode a = new BTNode('A');
		BTNode b = new BTNode('B', null, a);
		BTNode c = new BTNode('C');
		BTNode d = new BTNode('D', b, c);
		BTNode e = new BTNode('E');
		BTNode f = new BTNode('F', e, null);
		BTNode g = new BTNode('G', null, f);
		BTNode h = new BTNode('H', d, g);
		return h;         // 根結點
	}

	// 訪問節點
	public static void visit(BTNode p)
	{
		System.out.print(p.getKey() + " ");
	}

	// 遞歸實現前序遍歷
	protected static void preorder(BTNode p)
	{
		if (p != null)
		{
			visit(p);
			preorder(p.getLeft());
			preorder(p.getRight());
		}
	}

	// 遞歸實現中序遍歷
	protected static void inorder(BTNode p)
	{
		if (p != null)
		{
			inorder(p.getLeft());
			visit(p);
			inorder(p.getRight());
		}
	}

	// 遞歸實現後序遍歷
	protected static void postorder(BTNode p)
	{
		if (p != null)
		{
			postorder(p.getLeft());
			postorder(p.getRight());
			visit(p);
		}
	}

	// 非遞歸實現前序遍歷
	protected static void iterativePreorder(BTNode p)
	{
		Stack<BTNode> stack = new Stack<BTNode>();
		if (p != null)
		{
			stack.push(p);
			while (!stack.empty())
			{
				p = stack.pop();
				visit(p);
				if (p.getRight() != null)
					stack.push(p.getRight());
				if (p.getLeft() != null)
					stack.push(p.getLeft());
			}
		}
	}

	// 非遞歸實現後序遍歷
	protected static void iterativePostorder(BTNode p)
	{
		BTNode q = p;
		Stack<BTNode> stack = new Stack<BTNode>();
		while (p != null)
		{
			// 左子樹入棧
			for (; p.getLeft() != null; p = p.getLeft())
				stack.push(p);
			// 當前結點無右子結點或右子結點已經輸出
			while (p != null && (p.getRight() == null || p.getRight() == q))
			{
				visit(p);
				q = p;        // 記錄上一個已輸出結點
				if (stack.empty())
					return;
				p = stack.pop();
			}
			// 處理右子結點
			stack.push(p);
			p = p.getRight();
		}
	}

	// 非遞歸實現中序遍歷
	protected static void iterativeInorder(BTNode p)
	{
		Stack<BTNode> stack = new Stack<BTNode>();
		while (p != null)
		{
			while (p != null)
			{
				if (p.getRight() != null)
					stack.push(p.getRight());   // 當前結點右子結點入棧
				stack.push(p);                  // 當前結點入棧
				p = p.getLeft();
			}
			p = stack.pop();
			while (!stack.empty() && p.getRight() == null)
			{
				visit(p);
				p = stack.pop();
			}
			visit(p);
			if (!stack.empty())
				p = stack.pop();
			else
				p = null;
		}
	}

	public static void main(String[] args)
	{
		BinTree tree = new BinTree(init());

		System.out.print(" 遞歸實現前序遍歷:");
		preorder(tree.getRoot());
		System.out.println("\n");

		System.out.print(" 遞歸實現中序遍歷:");
		inorder(tree.getRoot());
		System.out.println("\n");

		System.out.print(" 遞歸實現後序遍歷:");
		postorder(tree.getRoot());
		System.out.println("\n");

		System.out.print(" 非遞歸實現前序遍歷:");
		iterativePreorder(tree.getRoot());
		System.out.println("\n");

		System.out.print(" 非遞歸實現中序遍歷:");
		iterativeInorder(tree.getRoot());
		System.out.println("\n");

		System.out.print(" 非遞歸實現後序遍歷:");
		iterativePostorder(tree.getRoot());
		System.out.println("\n");

	}
}



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