定義
最多有兩棵子樹的有序樹,稱為二叉樹。二叉樹是一種特殊的樹。
遞歸定義:二叉樹是n(n>=0)個有限結點構成的集合。N=0稱為空二叉樹;n>0的二叉樹由一個根結點和兩互不相交的,分別稱為左子樹和右子樹的二叉樹構成。
二叉樹中任何結點的第1個子樹稱為其左子樹,左子樹的根稱為該結點的左孩子;二叉樹中任何結點的第2個子樹稱為其右子樹,左子樹的根稱為該結點的右孩子。如下圖是一個二叉樹:
滿二叉樹和完全二叉樹
在一棵二叉樹中,如果所有分支結點都存在左子樹和右子樹,並且葉子結點都在同一層上,這樣的二叉樹稱作滿二叉樹。一棵深度為k且由2k-1個結點的二叉樹稱為滿二叉樹。
如果一棵具有n個結點的二叉樹的結構與滿二叉樹的前n個結點的結構相同,這樣的二叉樹稱作完全二叉樹。
基本性質
這里規定二叉樹的根結點的層次為1。
性質1:則二叉樹的第i 層最多有2i-1個結點(在此二叉樹的層次從1開始,i≥1)
性質2:深度為k的二叉樹最多有2k-1個結點。(k≥1)
性質3:對任何一棵二叉樹T, 如果其葉結點個數為n0, 度為2的非葉結點個數為n2, 則有
n0 = n2 + 1
性質4:具有 n(n>0)個結點的完全二叉樹的深度為⎣log2n⎦+1;⎦x⎦表示不超過x的最大整數。
性質5:如果對一棵有n個結點的完全二叉樹的結點按層序編號(從第1層到第⎣l og2n⎦ +1層,每層從左到右),則對任一結點i(1≤i≤n),有:
(1)如果i=1,則結點i無雙親,是二叉樹的根;如果i>1,則其雙親是結點⎣i/2⎦。
(2) 如果2i<=n, 則結點i的左孩子結點是2i;否則,結點i為葉子結點,無左孩子結點。
(3)如果2i+1<=n,則結點i的右孩子是結點2i+1; 否則,結點i為葉子結點,無右孩子結點。
抽象數據類型
數據元素:具有相同特性的數據元素的集合。
結構關系:樹中數據元素間的結構關系由二叉樹的定義確定。
基本操作:樹的主要操作有
(1)創建樹IntTree(&T)
(2)銷毀樹DestroyTree(&T)
(3)構造樹CreatTree(&T,deinition)
(4)置空樹ClearTree(&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())
二叉樹的實現
二叉樹接口BTree
package datastructure.tree.btree;
public interface BTree {
/**
* 添加左子樹
* @param lChild 左子樹
*/
public void addLeftTree(BTree lChild);
/**
* 添加右子樹
* @param rchild 右子樹
*/
public void addRightTree(BTree rchild) ;
/**
* 置空樹
*/
public void clearTree();
/**
* 求樹的深度
* @return 樹的深度
*/
public int dept();
/**
* 求左孩子 結點
* @return
*/
public BTree getLeftChild();
/**
* 求右孩子結點
* @return
*/
public BTree getRightChild();
/**
* 獲得根結點的數據
* @return
*/
public Object getRootData();
/**
* 是否有左子樹
* @return
*/
public boolean hasLeftTree();
/**
* 是否有右子樹
* @return
*/
public boolean hasRightTree();
/**
* 判斷是否為空樹
* @return 如果為空,返回true,否則返回false
*/
public boolean isEmpty();
/**
* 判斷是否為葉子結點
* @return
*/
public boolean isLeaf();
/**
* 刪除左子樹
*/
public void removeLeftChild();
/**
* 刪除右子樹
*/
public void removeRightChild();
/**
* 獲得樹根
* @return 樹的根
*/
public BTree root();
/**
* 設置根結點的數據
*/
public void setRootData(Object data);
/**
* 求結點數
* @return 結點的個數
*/
public int size();
}
二叉鏈表的實現
package datastructure.tree.btree;
public class LinkBTree implements BTree {
private Object data;
private BTree lChild;
private BTree rChild;
public LinkBTree() {
this.clearTree();
}
public LinkBTree(Object data) {
this.data = data;
this.lChild = null;
this.rChild = null;
}
@Override
public void addLeftTree(BTree lChild) {
this.lChild = lChild;
}
@Override
public void addRightTree(BTree rChild) {
this.rChild = rChild;
}
@Override
public void clearTree() {
this.data = null;
this.lChild = null;
this.rChild = null;
}
@Override
public int dept() {
return dept(this);
}
private int dept(BTree btree) {
if(btree.isEmpty()) {
return 0;
}else if(btree.isLeaf()) {
return 1;
} else {
if(btree.getLeftChild() == null) {
return dept(btree.getRightChild()) + 1;
} else if(btree.getRightChild() == null) {
return dept(btree.getLeftChild()) + 1;
} else {
return Math.max(dept(btree.getLeftChild()), dept(btree.getRightChild()))+1;
}
}
}
@Override
public BTree getLeftChild() {
return lChild;
}
@Override
public BTree getRightChild() {
return rChild;
}
@Override
public Object getRootData() {
return data;
}
@Override
public boolean hasLeftTree() {
if(lChild != null)
return true;
return false;
}
@Override
public boolean hasRightTree() {
if(rChild != null)
return true;
return false;
}
@Override
public boolean isEmpty() {
if((lChild == null && rChild == null && data == null) || this == null) {
return true;
}
return false;
}
@Override
public boolean isLeaf() {
if(lChild == null && rChild == null) {
return true;
}
return false;
}
@Override
public void removeLeftChild() {
lChild = null;
}
@Override
public void removeRightChild() {
rChild = null;
}
@Override
public BTree root() {
return this;
}
@Override
public void setRootData(Object data) {
this.data = data;
}
@Override
public int size() {
return size(this);
}
private int size(BTree btree) {
if(btree == null)
return 0;
else if(btree.isLeaf())
return 1;
else {
if(btree.getLeftChild() == null) {
return size(btree.getRightChild()) + 1;
} else if(btree.getRightChild() == null) {
return size(btree.getLeftChild()) + 1;
} else {
return size(btree.getLeftChild()) + size(btree.getRightChild()) + 1;
}
}
}
}
二叉樹的遍歷
二叉樹的遍歷是指按照一定的次序訪問樹中所有結點,並且每個結點只被訪問一次的過程。通常的遍歷有三種方式,分別是:前序遍歷、中序遍歷和后序遍歷,假設根結點、左孩子結點和右孩子結點分別用D、R、L表示,則前序遍歷、中序遍歷和后序遍歷的順序分別為DLR、LDR、LRD。所謂訪問某結點,一般指對結點中的數據進行某種操作。所以,我們可以定義一個對結點中的數據進行操作的接口Visit,讓所有遍歷樹的類實現這個接口。
Visit接口:
package datastructure.tree;
/**
* 對結點進行操作的接口
* @author Administrator
*
*/
public interface Visit {
/**
* 對結點進行某種操作
* @param btree 樹的結點
*/
public void visit(BTree btree);
}
遍歷二叉樹
package datastructure.tree;
/**
* 遍歷二叉樹
* @author Administrator
*
*/
public class OrderBTree implements Visit{
/**
* 前序遍歷
* @param root 根結點
*/
public void preOrder(BTree root) {
visit(root);
if(root.getLeftChild() != null) {
preOrder(root.getLeftChild());
}
if(root.getRightChild() != null) {
preOrder(root.getRightChild());
}
}
/**
* 中序遍歷
* @param root 根結點
*/
public void inOrder(BTree root) {
if(root.getLeftChild() != null)
inOrder(root.getLeftChild());
visit(root);
if(root.getRightChild() != null) {
//System.out.println("true");
inOrder(root.getRightChild());
}
}
/**
* 后序遍歷
* @param root 根結點
*/
public void postOrder(BTree root) {
if(root.getLeftChild() != null)
postOrder(root.getLeftChild());
if(root.getRightChild() != null)
postOrder(root.getRightChild());
visit(root);
}
@Override
public void visit(BTree btree) {
System.out.print(btree.getRootData() + "\t");
}
}
二叉樹的測試
package datastructure.tree;
/**
* 測試二叉樹
* @author Administrator
*
*/
public class BTreeTest {
public static void main(String args[]) {
BTree btree = new LinkBTree('A');
BTree bt1, bt2, bt3, bt4;
bt1 = new LinkBTree('B');
btree.addLeftTree(bt1);
bt2 = new LinkBTree('D');
bt1.addLeftTree(bt2);
bt3 = new LinkBTree('C');
btree.addRightTree(bt3);
bt4 = new LinkBTree('E');
bt3.addLeftTree(bt4);
bt4 = new LinkBTree('F');
bt3.addRightTree(bt4);
System.out.println("樹的深度:" + btree.dept());
System.out.println("樹的結點數:" + btree.size());
System.out.println("是否為空樹:" + btree.isEmpty());
System.out.println("是否為葉子結點:" + btree.isLeaf());
System.out.println("最左下邊結點是否為葉子結點:" + btree.getRightChild().getRightChild().isLeaf());
System.out.println("root結點:" + btree.root());
OrderBTree order = new OrderBTree();
System.out.println("\n前序遍歷:");
order.preOrder(btree);
System.out.println("\n中序遍歷:");
order.inOrder(btree);
System.out.println("\n后序遍歷:");
order.postOrder(btree);
btree.removeLeftChild();
System.out.println("\n刪除左子樹后中序遍歷為:");
order.inOrder(btree);
}
}
結果如下:
樹的深度:3
樹的結點數:6
是否為空樹:false
是否為葉子結點:false
最左下邊結點是否為葉子結點:true
root結點:datastructure.tree.LinkBTree@dc8569
前序遍歷:
A B DCEF
中序遍歷:
D B AECF
后序遍歷:
D B EFCA
刪除左子樹后中序遍歷為:
A E CF
轉載至:http://blog.csdn.net/luoweifu/article/details/9077521