二叉排序樹是資訊學競賽中乙個相當簡單又相當複雜的東西,其實考到的次數不多,但是還是挺常用的。
【定義】
二叉排序樹的定義是這樣的:設當前節點為o,且節點的資料結構是這樣的:
struct node則:o.left->value < o.value,o.right->value > o.value。在這裡不考慮重複的元素,則對於每乙個節點而言,這個節點的左孩子結點小於這個節點,右孩子節點大於這個節點。
因此我們可以得出推論:每一棵二叉排序樹的中序遍歷的序列是有序的!中序遍歷先訪問左孩子結點,再訪問當前節點,最後訪問右孩子節點。而」最左「的節點是最小的,」最左「的節點的父節點第二小……一直到」最右「的節點最大,這就是」二叉排序樹「的**,其中序遍歷的序列是有序的。
既然是一種這樣的資料結構,那自然就是可以維護乙個有序集合的。有序集合,就必須有查詢、插入、刪除之類的基本操作,下面來逐一介紹。
【查詢】
因為二叉排序樹的所有節點都滿足左子結點小於當前節點,右子結點大於當前子節點,所以我們可以用一種類似二分查詢的思路。比如說先比較當前的節點與待查詢值,如果相等就找到了,小於則像左邊遞迴搜尋,大於則向右邊遞迴搜尋。
const int not_found = -1;不過,這個過程也可以直接用迴圈迭代實現。迴圈的迭代更為高效,而且不會爆棧,所以可以處理更大規模的資料了,**如下:node* find(node* o,int x)
const int now_found = -1;【插入】node* find(node* o,int x)
return (o == null ? not_found : o);
}
插入同時也是很簡單的。插入是這樣的:先找到乙個符合要求的空位,接著直接插入,一般來說也是用遞迴的寫法。和查詢差不多。不過插入也可以認為是先找到位置再賦值。
void insert(node* &root,int x)因為是普通的二叉排序樹,所以說沒有那麼複雜。int d = root -> cmp(x);
if (d == 0) insert(root -> right,x);
else if (d == 1) insert(root -> left,x);
else if (d == -1) insert(root -> left,x);
}
【刪除】
刪除的操作倒比較麻煩了。首先,我們要分情況討論。如果當前要刪的節點是葉節點,那就直接刪,而其他的節點就不行了,要進行一些特殊的處理,使得這個節點變成乙個葉節點。一般來說,有兩種方法,分別是利用【旋轉】操作,還有一種的思路比較直觀,實現起來比較簡單的方法,只需要一次交換即可。但是最具有通用性的還是用【旋轉】操作。在這裡,我們就順便定義一下【旋轉】操作。
【旋轉】
考慮下面的兩顆樹,可以發現,它們的中序遍歷序列是一樣的,但是節點的位置卻發生了改變。
它們的中序遍歷都是aobkc,但是點o不再是根了。這說明,我們可以在不改變二叉排序樹性質的情況下,改變二叉排序樹的形態!實際上,在旋轉中,從第一張圖的形態變為第二張圖的形態,叫做左旋,其逆操作叫做右旋。這是很形象的名字。觀察一下,我們只需要改變o的右孩子,k的左孩子,也就是說,**很簡短。下面是左旋和右旋的**:
左旋:
void left_rotate(node* o)右旋:
void right_rotate(node* k)【刪除(續)】
講完了旋轉,繼續回到刪除。
既然要把某個點從其本來的位置一直移到葉節點上,那麼我們完全可以一直旋轉。在node型別中多記乙個size,表示以當前節點為根的子樹大小,而每一次旋轉的時候都要維護一下,不難寫出相應的maintain()函式,思路很直觀。
然後,就一直將節點向子樹大小較小的那一邊旋轉即可,很顯然必定會旋轉到葉節點。不過要加乙個特判,不然的話就訪問了指向null的節點的大小了。指向null的節點的size應該是0。用乙個迭代的寫法就很容易寫出來了,非常類似於查詢和插入。
void _delete(node* o)o = null;
}
二叉排序樹
在複習資料結構,把這個東西總結一下。這種結構是動態查詢表,這種動態是相對靜態查詢 順序查詢,折半查詢,分塊查詢等 來說的。對於各種靜態鍊錶,要達到查詢複雜度為o logn 必須要求有序 而要使插入刪除複雜度為o 1 必須是鍊錶儲存。動態查詢表就可以同時滿足這兩者。動態查詢表的特點是表結構本身在查詢過...
二叉排序樹
name 二叉排序樹相關操作 author unimen date 2011 10 8 13 14 21 刪除結點比較麻煩,總結如下 4大種情況 1 結點p無右孩子 將該點的左孩子變為其在雙親中的同位孩子 1 p為其雙親的左孩子時將其的左孩子變為雙親的左孩子 2 p為其雙親的右孩子時將其的左孩子變為...
二叉排序樹
include include include include struct tree node void insert node struct tree node int void pre order struct tree node void in order struct tree node ...