樹的定義
樹(Tree)是n(n≥0)個結點的有限集T,并且當n>0時滿足下列條件:
1.有且僅有一個特定的稱為根(Root)的結點;
2.當n>1時,其余結點可以劃分為m(m>0)個互不相交的有限集T1、T2 、…、Tm,每個集Ti(1≤i≤m)均為樹,且稱為樹T的子樹(SubTree)。
不含任何結點(即n=0)的樹,稱為空樹。
如下圖就是一棵樹的結構:
樹的基本術語
結點:存儲數據元素和指向子樹的鏈接,由數據元素和構造數據元素之間關系的引用組成。
孩子結點:樹中一個結點的子樹的根結點稱為這個結點的孩子結點,如上圖中的A的孩子結點有B、C、D
雙親結點:樹中某個結點有孩子結點(即該結點的度不為0),該結點稱為它孩子結點的雙親結點,也叫前驅結點。雙親結點和孩子結點是相互的,如上圖中,A的孩子結點是B、C、D,B、C、D的雙親結點是A。
兄弟結點:具有相同雙親結點(即同一個前驅)的結點稱為兄弟結點,如上圖中B、B、D為兄弟結點。
結點的度:結點所有子樹的個數稱為該結點的度,如上圖,A的度為3,B的度為2.
樹的度:樹中所有結點的度的最大值稱為樹的度,如上圖的度為3.
葉子結點:度為0的結點稱為葉子結點,也叫終端結點。如上圖的K、L、F、G、M、I、J
分支結點:度不為0的結點稱為分支結點,也叫非終端結點。如上圖的A、B、C、D、E、H
結點的層次:從根結點到樹中某結點所經路徑的分支數稱為該結點的層次。根結點的層次一般為1(也可以自己定義為0),這樣,其它結點的層次是其雙親結點的層次加1.
樹的深度:樹中所有結點的層次的最大值稱為該樹的深度(也就是最下面那個結點的層次)。
有序樹和無序樹:樹中任意一個結點的各子樹按從左到右是有序的,稱為有序樹,否則稱為無序樹。
樹的抽象數據類型描述
ADT 樹(Tree)
Data
具有相同特性的數據元素的集合;樹中數據元素間的結構關系由樹的定義確定。
Operation
(1)initTree(T):創建1個空樹T
(2)destroyTree(T):銷毀樹
(3)creatTree(T,deinition):構造樹
(4)clearTree(T):置空樹,將樹T置為空樹
(5)treeEmpty(T):判空樹
(6)treeDepth(T):求樹的深度
(7)root(T):獲得樹根
(8)value(T,cur_e,e):獲取結點,將樹中結點cur_e存入e單元中。
(9)assign(T,cur_e,value):數據賦值,將結點value,賦值于樹T的結點cur_e中。
(10)parent(T,cur_e):獲得雙親, 返回樹T中結點cur_e的雙親結點。
(11)leftChild(T,cur_e):獲得最左孩子,返回樹T中結點cur_e的最左孩子。
(12)rightSibling(T,cur_e):獲得右兄弟,返回樹T中結點cur_e的右兄弟。
(13)InsertChild(T,p,i,c):插入子樹,將樹c插入到樹T中p指向結點的第i個子樹之前。
(14)deleteChild(T,p,i):刪除子樹, 刪除樹T中p指向結點的第i個子樹。
(15)traverseTree(T,visit()):遍歷樹
endADT
樹的實現
樹是一種遞歸結構,表示方式一般有孩子兄弟表示法和孩子表示法兩種。樹實現方式有很多種、有可以由廣義表的遞歸實現,也可以有二叉樹實現,其中最常見的是將樹用孩子兄弟表示法轉化成二叉樹來實現,如下圖:
/**
* 以孩子表示法為例講一下樹的實現
* @author wangxiaojian
*/
public class Tree {
private Object data;
private List<Tree> childs;
public Tree() {
data = null;
childs = new ArrayList<>();
}
public Tree(Object data) {
this.data = data;
childs = new ArrayList<>();
}
/**
* 添加子樹
*
* @param tree 子樹
*/
public void addNode(Tree tree) {
childs.add(tree);
}
/**
* 置空樹
*/
public void clearTree() {
data = null;
childs.clear();
}
/**
* 求樹的深度
*
* @return 樹的深度
*/
public int dept() {
return dept(this);
}
/**
* 求樹的深度
*
* @param tree
* @return
*/
private int dept(Tree tree) {
if (tree.isEmpty()) {
return 0;
} else if (tree.isLeaf()) {
return 1;
} else {
int n = childs.size();
int[] a = new int[n];
for (int i = 0; i < n; i++) {
if (childs.get(i).isEmpty()) {
a[i] = 0 + 1;
} else {
a[i] = dept(childs.get(i)) + 1;
}
}
Arrays.sort(a);
return a[n - 1];
}
}
/**
* 返回遞i個子樹
*
* @param i
* @return
*/
public Tree getChild(int i) {
return childs.get(i);
}
/**
* 求第一個孩子 結點
*
* @return
*/
public Tree getFirstChild() {
return childs.get(0);
}
/**
* 求最后 一個孩子結點
*
* @return
*/
public Tree getLastChild() {
return childs.get(childs.size() - 1);
}
public List<Tree> getChilds() {
return childs;
}
/**
* 獲得根結點的數據
*
* @return
*/
public Object getRootData() {
return data;
}
/**
* 判斷是否為空樹
*
* @return 如果為空,返回true,否則返回false
*/
public boolean isEmpty() {
if (childs.isEmpty() && data == null) {
return true;
}
return false;
}
/**
* 判斷是否為葉子結點
*
* @return
*/
public boolean isLeaf() {
if (childs.isEmpty()) {
return true;
}
return false;
}
/**
* 獲得樹根
*
* @return 樹的根
*/
public Tree root() {
return this;
}
/**
* 設置根結點的數據
*/
public void setRootData(Object data) {
this.data = data;
}
/**
* 求結點數
*
* @return 結點的個數
*/
public int size() {
return size(this);
}
/**
* 求結點數
*
* @param tree
* @return
*/
private int size(Tree tree) {
if (tree.isEmpty()) {
return 0;
} else if (tree.isLeaf()) {
return 1;
} else {
int count = 1;
int n = childs.size();
for(int i=0; i<n; i++) {
if(!childs.get(i).isEmpty()) {
count += size(childs.get(i));
}
}
return count;
}
}
}