文章目錄
一、基本含義
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;
}
}