二叉排序樹

2021-07-09 22:58:40 字數 2231 閱讀 3238

二叉排序樹是資訊學競賽中乙個相當簡單又相當複雜的東西,其實考到的次數不多,但是還是挺常用的。

【定義】

二叉排序樹的定義是這樣的:設當前節點為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 ...