樹定義和基本術語
定義
樹(Tree)是n(n≥0)個結點的有限集T,而且當n>0時知足下列條件:
(1)有且僅有一個特定的稱爲根(Root)的結點;
(2)當n>1時,其他結點能夠劃分爲m(m>0)個互不相交的有限集T一、T2 、…、Tm,每一個集Ti(1≤i≤m)均爲樹,且稱爲樹T的子樹(SubTree)。
特別地,不含任何結點(即n=0)的樹,稱爲空樹。
以下就是一棵樹的結構:java
圖1
基本術語
結點:存儲數據元素和指向子樹的連接,由數據元素和構造數據元素之間關係的引用組成。
孩子結點:樹中一個結點的子樹的根結點稱爲這個結點的孩子結點,如圖1中的A的孩子結點有B、C、D
雙親結點:樹中某個結點有孩子結點(即該結點的度不爲0),該結點稱爲它孩子結點的雙親結點,也叫前驅結點。雙親結點和孩子結點是相互的,如圖1中,A的孩子結點是B、C、D,B、C、D的雙親結點是A。
兄弟結點:具備相同雙親結點(即同一個前驅)的結點稱爲兄弟結點,如圖1中B、B、D爲兄弟結點。
結點的度:結點全部子樹的個數稱爲該結點的度,如圖1,A的度爲3,B的度爲2.
樹的度:樹中全部結點的度的最大值稱爲樹的度,如圖1的度爲3.
葉子結點:度爲0的結點稱爲葉子結點,也叫終端結點。如圖1的K、L、F、G、M、I、J
分支結點:度不爲0的結點稱爲分支結點,也叫非終端結點。如圖1的A、B、C、D、E、H
結點的層次:從根結點到樹中某結點所經路徑的分支數稱爲該結點的層次。根結點的層次通常爲1(也能夠本身定義爲0),這樣,其它結點的層次是其雙親結點的層次加1.
樹的深度:樹中全部結點的層次的最大值稱爲該樹的深度(也就是最下面那個結點的層次)。
有序樹和無序樹:樹中任意一個結點的各子樹按從左到右是有序的,稱爲有序樹,不然稱爲無序樹。
樹的抽象數據類型描述
數據元素:具備相同特性的數據元素的集合。
結構關係:樹中數據元素間的結構關係由樹的定義肯定。
基本操做:樹的主要操做有
(1)建立樹IntTree(&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())
樹的實現
樹是一種遞歸結構,表示方式通常有孩子表示法和孩子兄弟表示法兩種。樹實現方式有不少種、有能夠由廣義表的遞歸實現,也能夠有二叉樹實現,其中最多見的是將樹用孩子兄弟表示法轉化成二叉樹來實現。
下面以孩子表示法爲例講一下樹的實現:
樹的定義和實現
package datastructure.tree;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.LinkedList;
import java.util.List;
/**
* 樹的定義和實現
* @author Administrator
*
*/
public class Tree {
private Object data;
private List<Tree> childs;
public Tree(){
data = null;
childs = new ArrayList();
childs.clear();
}
public Tree(Object data) {
this.data = data;
childs = new ArrayList();
childs.clear();
}
/**
* 添加子樹
* @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;
}
}
}
樹的遍歷
樹的遍歷有兩種
前根遍歷
(1).訪問根結點;
(2).按照從左到右的次序行根遍歷根結點的第一棵子樹;
後根遍歷
(1).按照從左到右的次序行根遍歷根結點的第一棵子樹;
(2).訪問根結點;
Visit.Java
package datastructure.tree;
import datastructure.tree.btree.BTree;
/**
* 對結點進行操做的接口,規定樹的遍歷的類必須實現這個接口
* @author Administrator
*
*/
public interface Visit {
/**
* 對結點進行某種操做
* @param btree 樹的結點
*/
public void visit(BTree btree);
}
order.java
package datastructure.tree;
import java.util.List;
/**
* 樹的遍歷
* @author Administrator
*
*/
public class Order {
/**
* 先根遍歷
* @param root 要的根結點
*/
public void preOrder(Tree root) {
if(!root.isEmpty()) {
visit(root);
for(Tree child : root.getChilds()) {
if(child != null) {
preOrder(child);
}
}
}
}
/**
* 後根遍歷
* @param root 樹的根結點
*/
public void postOrder(Tree root) {
if(!root.isEmpty()) {
for(Tree child : root.getChilds()) {
if(child != null) {
preOrder(child);
}
}
visit(root);
}
}
public void visit(Tree tree) {
System.out.print("\t" + tree.getRootData());
}
}
測試:
要遍歷的樹以下:node
package datastructure.tree;
import java.util.Iterator;
import java.util.Scanner;
public class TreeTest {
/**
* @param args
*/
public static void main(String[] args) {
Tree root = new Tree("A");
root.addNode(new Tree("B"));
root.addNode(new Tree("C"));
root.addNode(new Tree("D"));
Tree t = null;
t = root.getChild(0);
t.addNode(new Tree("L"));
t.addNode(new Tree("E"));
t = root.getChild(1);
t.addNode(new Tree("F"));
t = root.getChild(2);
t.addNode(new Tree("I"));
t.addNode(new Tree("H"));
t = t.getFirstChild();
t.addNode(new Tree("L"));
System.out.println("first node:" + root.getRootData());
//System.out.println("size:" + root.size());
//System.out.println("dept:" + root.dept());
System.out.println("is left:" + root.isLeaf());
System.out.println("data:" + root.getRootData());
Order order = new Order();
System.out.println("前根遍歷:");
order.preOrder(root);
System.out.println("\n後根遍歷:");
order.postOrder(root);
}
}
結果:
first node:A
is left:false
data:A
前根遍歷:
A BL E C F DI L H
後根遍歷:
B LE C F D IL H Apost
轉載至:http://blog.csdn.net/luoweifu/article/details/9071849測試