《java常用演算法手冊》 第二章 資料結構 樹 圖
阿新 • • 發佈:2018-11-01
前面我們介紹陣列的資料結構,我們知道對於有序陣列,查詢很快,並介紹可以通過二分法查詢,但是想要在有序陣列中插入一個數據項,就必須先找到插入資料項的位置,然後將所有插入位置後面的資料項全部向後移動一位,來給新資料騰出空間,平均來講要移動N/2次,這是很費時的。同理,刪除資料也是。
然後我們介紹了另外一種資料結構——連結串列,連結串列的插入和刪除很快,我們只需要改變一些引用值就行了,但是查詢資料卻很慢了,因為不管我們查詢什麼資料,都需要從連結串列的第一個資料項開始,遍歷到找到所需資料項為止,這個查詢也是平均需要比較N/2次。
那麼我們就希望一種資料結構能同時具備陣列查詢快的優點以及連結串列插入和刪除快的優點,於是 樹 誕生了。
深度為路徑長度
A(D(I(N,M(Q,P)),H),C(G,F(J)),B(E(L(O),K)))
//二叉排序樹
//我們就希望一種資料結構能同時具備陣列查詢快的優點以及連結串列插入和刪除快的優點,於是 樹 誕生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我們給二叉樹加一個額外的條件,就可以得到一種被稱作二叉搜尋樹(binary search tree)的特殊二叉樹。
//二叉搜尋樹要求:若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。
//待插入的節點也需要從根節點開始進行比較,小於根節點則與根節點左子樹比較,反之則與右子樹比較,直到左子樹為空或右子樹為空,則插入到相應為空的位置
//,在比較的過程中要注意儲存父節點的資訊 及 待插入的位置是父節點的左子樹還是右子樹,才能插入到正確的位置。
刪除節點
刪除節點是二叉搜尋樹中最複雜的操作,刪除的節點有三種情況,前兩種比較簡單,但是第三種卻很複雜。
1、該節點是葉節點(沒有子節點)
2、該節點有一個子節點
3、該節點有兩個子節點
package LineStructure;
//二叉排序樹
//我們就希望一種資料結構能同時具備陣列查詢快的優點以及連結串列插入和刪除快的優點,於是 樹 誕生了。
//https://www.cnblogs.com/ysocean/p/8032642.html
//如果我們給二叉樹加一個額外的條件,就可以得到一種被稱作二叉搜尋樹(binary search tree)的特殊二叉樹。
//二叉搜尋樹要求:若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值; 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值; 它的左、右子樹也分別為二叉排序樹。
public class LinkedTree<T> extends Object {
Node root;
private class Node {
private int data;
private Node leftChild;
private Node rightChild;
public Node(int data) {
this.data = data;
}
public int getData() {
return data;
}
}
public LinkedTree() {
}
//
public LinkedTree(Node root) {
this.root = root;
}
// get root
public Node getRoot() {
return this.root;
}
// set root
public void setRoot(Node root) {
this.root = root;
}
//待插入的節點也需要從根節點開始進行比較,小於根節點則與根節點左子樹比較,反之則與右子樹比較,直到左子樹為空或右子樹為空,則插入到相應為空的位置
//,在比較的過程中要注意儲存父節點的資訊 及 待插入的位置是父節點的左子樹還是右子樹,才能插入到正確的位置。
public Boolean insert(int data) {
String error = null;
Node node = new Node(data);
if (root == null) {
root = node;
root.leftChild = null;
root.rightChild = null;
} else {
//start to Search
Node current = root;
//儲存一個 parent 用來插入時指定插入點的parent以及葉子節點
Node parent = null;
//searchTree
while (true) {
parent = current; //指定插入點的parent
if(data < current.data) {
current = current.leftChild; //searchLeftTree
if(current == null) {
parent.leftChild = node;//指定插入點的位置
return true;
}
}else {
current = current.rightChild;
if(current == null) {
parent.rightChild = node;//指定插入點的位置
return true;
}
}
}
}
return false;
}
public Boolean delete() {
return null;
}
//查詢樹 注意並不是遍歷 因為是二叉搜尋樹 所以查詢時並不會遍歷所有節點
//查詢節點的時間取決於這個節點所在的層數,每一層最多有2n-1個節點,總共N層共有2n-1個節點,那麼時間複雜度為O(logn),底數為2。
public Node find(int data) {
Node temp = root;
while(temp != null) {
if(temp.data == data) {
return temp;
}else if(data < temp.data) {
temp = temp.leftChild;
}else if(data > temp.data) {
temp = temp.rightChild;
}
}
return null;
}
public void middleOrder(Node current) {
if(current != null) {
middleOrder(current.leftChild);
System.out.println(current.data);
middleOrder(current.rightChild);
}
}
public void preOrder(Node current) {
if(current != null) {
System.out.println(current.data);
preOrder(current.leftChild);
preOrder(current.rightChild);
}
}
public void postOrder(Node current) {
if(current != null) {
postOrder(current.leftChild);
postOrder(current.rightChild);
System.out.println(current.data);
}
}
//查詢最大值節點 直接找右子樹
public Node findMax() {
Node current = root;
Node maxNode = null;
while(current != null) {
current = current.rightChild;
maxNode = current;
}
return maxNode;
}
//查詢最小值 直接找左子樹
public Node findMin() {
Node current = root;
//之前的寫法 錯誤 current可能為空
/*while(current != null) {
current = current.leftChild;
}
return current;*/
Node MinNode = null;
while(current != null) {
current = current.leftChild;
MinNode = current;
}
return MinNode;
}
//刪除節點
}