數據結構與算法-二叉樹

一、基本含義

1.1 樹結構

樹結構:樹是一種非線性的數據結構,相對於線性的數據結構(鏈表、數組)而言,樹的平均運行時間更短(往往與樹相關的排序時間複雜度都不會高)。
根節點:樹根。
葉子:沒有子節點的節點。
深度:代數。
注意
1、樹是非線性的,計算機的內存是線性存儲的。
2、在編程的世界中,一般把樹“倒”過來看。

1.2 定義樹

注意:一棵樹至少會有一個節點(根節點)。
樹由節點組成。
定義樹的順序:定義節點->節點連接起來就成了樹。
定義節點:一個數據、兩個指針(如果有節點就指向節點、沒有節點就指向null)。

1.3 二叉樹

二叉樹含義
1、是最簡單又經常用的樹結構。
2、一個節點的子節點個數不能超過2。
二叉查找樹(binary search tree):一種特殊的二叉樹。
二叉查找樹定義:當前根節點的左邊全部比根節點小,當前根節點的右邊全部比根節點大。

二、創建二叉樹

原理:
1、樹是由若干個節點組成,節點連接起來就成了樹。
2、節點由一個數據、兩個指針組成。
3、創建樹實際上就是創建節點,然後連接節點。

2.1 靜態創建

在這裏插入圖片描述
第一步:創建節點類。
TreeNode.java

public class TreeNode {	
	private TreeNode leftNode; // 左節點   	
	private TreeNode rightNode;// 右節點	
	private int value;// 數據
	public TreeNode(int value){
		this.value = value;
	}
}

第二步:創建節點
App.java

public static void main ( String [] args) {
 	//根節點-->10       
	TreeNode treeNode1 = new TreeNode (10);
	//左孩子-->9
	TreeNode treeNode2 = new TreeNode (9);        
	//右孩子-->20       
	TreeNode treeNode3 = new TreeNode(20);        
	//20的左孩子-->15
	TreeNode treeNode4 = new TreeNode(15);        
	//20的右孩子-->35        
	TreeNode treeNode5 = new TreeNode(35);       
}

第三步:連接節點
App.java

public static void main ( String [] args) {
 	//根節點的左右孩子
	treeNode1.setLeftNode(treeNode2);
	treeNode1.setRightNode(treeNode3);
	//20節點的左右孩子        
	treeNode3.setLeftNode(treeNode4);
	treeNode3.setRightNode(treeNode5);       
}

2.2 動態創建

注意:一般創建的是二叉查找樹,即無論任何一顆子樹,左邊都比根要小,右邊比根要大。
步驟
1、創建節點類。
2、判斷是否有根節點
——若無,則創建節點(當前值),直接作爲根節點。
——若有,則當前值與根節點值比較。
3、對比當前值與根節點值。
——若大,則進入右節點。
——若小,則進入左節點。
4、判斷左(右)節點是否有值。
——若無,則創建節點(當前值),作爲左(右)節點。
——若有,則把左(右)節點作爲根節點,重複3、4步驟。
TreeNode.java

public class TreeNode {	
	private TreeNode treeRoot; // 父節點。
	private TreeNode leftNode; // 左子節點   	
	private TreeNode rightNode;// 右子節點	
	private int value;// 當前節點數據。
	// setter/getter方法。	
	public TreeNode(int value){
		this.value = value;
	}
}

App.java

public static void createTree(TreeNode treeRoot,int value){	
	// 第一步:獲取當前節點的父節點。
	TreeNode tempRoot = treeRoot.getTreeRoot();
	// 第二步:判斷父節點是否有值。
	if(tempRoot == null){
		// 父節點無值,則當前節點設爲父節點。
		TreeNode treeNode = new TreeNode(value);
		treeRoot.setTreeRoot(treeNode);
	}else{
		// 父節點有值,則繼續向下尋找合適位置。
		while(tempRoot != null){
			// 當前值是否大於根節點值。
			if(value > tempRoot.getVlaue()){				
				//右邊沒有樹根,那就直接插入
				if(tempRoot.getRightNode() == null){
					tempRoot.setRightNode(new TreeNode(value));
					return;
				}else{
					//如果右邊有樹根,到右邊的樹根去
					tempRoot = tempRoot.getRightNode();
				}
			}else{
				//左邊沒有樹根,那就直接插入
				if(tempRoot.getLeftNode() == null){
					tempRoot.setLeftNode(new TreeNode(value));
					return;
				}else{
					//如果左邊有樹根,到右邊的樹根去
					tempRoot = tempRoot.getLeftNode();
				}				
			}
		}
	}
}
// 測試。
public static void main(string[] arg){
	int[] arr = {2,3,1,4,5};
	TreeNode treeNode = new TreeNode(); 
	for(int value: arr){
		createTree(treeNode,value);
	}
	preTraverseBtree(treeNode.getTreeRoot());
}

三、遍歷二叉樹

先序(根->左->右),中序(左->根->右),後序(左->右->根)。如果訪問有孩子的節點,先處理孩子的,隨後返回。

3.1 先序遍歷

含義:先訪問根節點,然後訪問左節點,最後訪問右節點(根->左->右)。
示例:10->9->20->15->35

public static void preTraverseBtree(TreeNode rootTreeNode){
	if(rootTreeNode != null){
		System.out.println(rootTreeNode.getValue);
		preTraverseBtree(rootTreeNode.getLeftNode());
		preTraverseBtree(rootTreeNode.getRightNode());
	}
}

3.2 中序遍歷

含義:先訪問左節點,然後訪問根節點,最後訪問右節點(左->根->右)。
示例:9->10->15->20->35

public static void inTraverseBtree(TreeNode rootTreeNode){
	if(rootTreeNode != null){
		preTraverseBtree(rootTreeNode.getLeftNode());
		System.out.println(rootTreeNode.getValue);		
		preTraverseBtree(rootTreeNode.getRightNode());
	}
}

3.3 後序遍歷

含義:先訪問左節點,然後訪問右節點,最後訪問根節點(左->右->根)。
示例:9->15->35->20->10

public static void inTraverseBtree(TreeNode rootTreeNode){
	if(rootTreeNode != null){
		preTraverseBtree(rootTreeNode.getLeftNode());
		preTraverseBtree(rootTreeNode.getRightNode());		
		System.out.println(rootTreeNode.getValue);		
	}
}

四、查詢二叉查找樹相關

4.1 查詢樹的深度

思路:
1、當左(右)節點再無子節點時,返回值爲0。
2、以當前節點爲末代,向上尋找父節點,直到根節點,每找到一個父節點,返回值+1。
3、左邊和右邊的返回值比,誰大就返回誰。

public static int getHeight(TreeNode treeNode){
	if(treeNode == null){
		return 0; // 初始值。
	}else{
		int left = getHeight(treeNode.getLeftNode());
		int right = getHeight(treeNode.getRightNode());
		int max = right > left ? right:left;
		return max + 1;
	}
}

4.2 查詢樹的最大值

思路:
1、左邊找最大值->遞歸。
2、右邊找最大值->遞歸。
3、選取左最大、右最大、根節點三者中的最大值。

public static int getMax(TreeNode treeNode){
	if(treeNode == null){
		return -1; 
	}else{
		int left = getMax(treeNode.getLeftNode());
		int right = getMax(treeNode.getRightNode());
		int currenRootValue = treeNode.getValue();
		int max = right > left ? right:left;
		max = max > currenRootValue ? max : currenRootValue;
		return max;
	}
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章