**
當所有的靜態查詢結構新增和刪除乙個資料的時候,整個結構都需要重建。這對於常常需要在查詢過程中動態改變資料而言,是災難性的。因此人們就必須去尋找高效的動態查詢結構,我們在這討論乙個非常常用的動態查詢樹——二叉查詢樹 。
二叉查詢樹的特點:
(1) 若它的左子樹不空,則左子樹上所有結點的值均小於它的根結點的值
(2) 若它的右子樹不空,則右子樹上所有結點的值均大於它的根結點的值
(3) 它的左、右子樹也分別為二叉查詢樹
我們中序遍歷這兩棵樹發現乙個有序的資料序列: 【1 2 3 4 5 6 7 8 】
1、查詢操作
在a圖中查詢關鍵字6
1)如果數為空,查詢失敗
2)比較6和根節點,如果相等,查詢成功,如果6大於根節點,轉向節點的右子樹,如果小於6,轉向節點的左子樹;
3)遞迴查詢每乙個節點,直到找到和6相等的節點,否則查詢失敗。
2、插入操作:
現在我們要查詢乙個數9,如果不存在則,新增進a圖。我們看看二叉查詢樹動態新增的過程:
1). 數9和根節點4比較(9>4),則9放在節點4的右子樹中。
2). 接著,9和節點5比較(9>5),則9放在節點5的右子樹中。
3). 依次類推:直到9和節點8比較(9>8),則9放在節點8的右子樹中,成為節點8的右孩子。
這個過程我們能夠發現,動態新增任何乙個資料,都會加在原樹結構的葉子節點上,而不會重新建樹。 由此可見,動態查詢結構確實在這方面有巨大的優勢。
3、刪除操作:假設p指向待刪除的節點,parent指向p的父母節點。刪除p節點分為3中情況,根據不同的情況有不同的操作:
1)p是葉節點,直接刪除
2)需要刪除的節點只有乙個左子樹或右子樹,用子樹代替該點
3)需要刪除的節點左、右子樹都存在,此時不直接刪除p節點,而是用p節點在中序遍歷下的第乙個後續節點s代替p節點,然後刪除s節點。這樣將3)轉化為1)或者2)的問題。因為p在中序遍歷下的後續節點要麼是其右子節點且為葉子結點,要麼是右子樹中最左邊的乙個子孫節點,度為0或者1.
package binarytree;
/* * 二叉樹查詢樹的表示和操作
* 1、構建二叉樹查詢樹
* 2、二叉樹查詢樹的查詢,包括任意乙個值,最大值,最小值,任意值的前驅和後繼
* 3、二叉樹查詢樹的插入和刪除
* */
public
class
bstdemo
public node getroot()
//查詢,遞迴
public
intfind(node node,int value)
if(node.getkey()==value)
if(node.getkey()>value)
if(node.getkey()return find(node.getrchild(),value);
}return value;
}//查詢,非遞迴
public
intloopfind(node node,int value)
if(node.getkey()>value)
else
}system.out.println("查詢失敗");
return value;
}//查詢最小值
public node getmin(node node)
return node;
}//查詢最大值
public node getmax(node node)
return node;
}//獲取給定點的前驅
public node getpredecessor(node node)
//如果左子樹為空
node p=node.getparent();
node x;
while(p!=null && node==p.getlchild())
return p;
}//獲取給頂點的後繼
public node getsuccessor(node node)
//如果右子樹空
node p=node.getparent();
node x;
while(p!=null && node==p.getrchild())
return p;
}//插入,非遞迴
public
void
insert(int value)
//如果樹不為空,則查詢插入合適的位置
node node=root;
while(node!=null)
if(node.getkey()>value)else node=node.getlchild();
}elseelse node=node.getrchild();}}
}public
void
insertall(int array)
}//給定乙個節點,並刪除
public
void
remove(node node)else
if(node.getrchild()==null)else
//如果直接後繼是node的右子樹,因為suc沒有左子樹,所以用suc直接代替node
trans(node,suc);
suc.setlchild(node.getlchild());
suc.getlchild().setparent(node);}}
//用y替換x
public
void
trans(node x,node y)else
if(x==x.getparent().getlchild())else x.getparent().setrchild(y);
if(y==null)
}//判斷乙個二叉樹是否為二叉查詢樹
public
boolean
issorted(node node){
if(node==null) return
true;
return (node.getlchild()==null || node.getlchild()!=null && node.getkey()>node.getlchild().getkey()&& node.getrchild()==null || node.getrchild()!=null && node.getkey()由於二叉查詢樹的插入和刪除操作花費時間的主要部分是查詢操作,所以二叉查詢樹的各操作效能有查詢效率決定。
在一棵有n個節點的二叉差值奧數中查詢乙個節點,一次成功的查詢剛好做過一條從根節點到該節點的路徑,比較次數為該節點的高度level,1≤
leve
l≤h ,其中h是樹的高度。所以二叉查詢樹查詢成功的平均查詢長度不大於該樹的高度。而二叉查詢樹的高度和其形態有關,n個節點的文案二叉樹高度最小,為⌊l
ogn⌋
+1,n個節點的單支二叉樹高度最大,高度為n。所以二叉查詢樹的平均查詢長度為o(
logn
)−−o
(n) 。
二叉查詢樹的查詢效率與二叉樹的高度有關,高度越低,查處效率越高。因此,提高二叉查詢樹查詢效率的辦法是盡量降低二叉查詢樹的高度。
3 二叉查詢樹
二叉查詢樹要求,在樹中的任意乙個節點,其左子樹中的每個節點的值,都要小於這個節點的值,而右子樹節點的值都大於這個節點的值。刪除的情況比較複雜 第一種情況是,如果要刪除的節點沒有子節點,我們只需要直接將父節點中,指向要刪除節點的 指標置為 null。第二種情況是,如果要刪除的節點只有乙個子節點 只有左...
樹 二叉樹 查詢演算法總結
一 樹 樹的基本操作 二 二叉樹 最優二叉樹 哈夫曼樹 在所有含 n 個葉子結點 並帶相同權值的 m 叉樹中,必存在一棵其帶權路徑長度取最小值的樹,稱為 最優樹 赫夫曼演算法 以二叉樹為例 根據給定的 n 個權值 構造 n 棵二叉樹的集合f 其中每棵二叉樹中均只含乙個帶權值為 wi 的根結點,其左 ...
樹 二叉樹 查詢演算法總結
結點的子樹的個數稱為該結點的度,乙個樹中所有結點的度中的最大值稱為樹的度。1 在非空二叉樹中,第i層的結點總數不超過,i 1。2 深度為h的二叉樹最多有個結點 h 1 最少有h個結點。3 對於任意一棵二叉樹,如果其葉結點數為n0,而度數為2的結點總數為n2,則n0 n2 1。有n個結點的完全二叉樹各...