二叉查詢樹又名二叉排序樹、二叉搜尋樹、bst(binary search tree)。首先知道它的基礎資料結構。
它是一顆二叉樹(帶權),通常會用結構體實現(陣列或者指標——個人比較喜歡用陣列,之後的**也是用陣列來實現的)。
structnodetree[size];
int tot; //
記錄共有幾個節點
int root; //
記錄根節點
不過它有乙個性質:對於任意乙個非葉子節點,它的左子樹所有的節點的權值都《他的權值,它的右子樹所有的節點的權值》它的權值。
其次它可以實現以下功能:
• 建立關鍵碼為x的節點
• 檢索
• 插入關鍵碼為x的節點
• 求關鍵碼為x的節點的前驅
• 求關鍵碼為x的節點的後繼
• 刪除關鍵碼為x的節點
update:求排名和排名的關鍵碼
• 求關鍵碼為x的節點的排名
• 求排名為x的節點的關鍵碼
1,建立關鍵碼
這個沒什麼好講的吧。
//插入乙個權值為v的新節點
int new(int
v)
2,bst的檢索
在bst中檢索是否存在權值為v的節點。
設變數p等於根節點root,執行以下過程:
1.若p的權值等於v,則已經找到
2.若p的權值大於v
a.若p的左子節點為空,則說明不存在v
b.若p的左子節點不空,在p的左子樹中遞迴進行檢索
3.若p的權值小於v
a.若p的右子節點為空,則說明不存在v
b.若p的右子節點不空,在p的右子樹中遞迴進行檢索
//檢索關鍵碼為v的編號
int find(int p, int
v)
3,bst的插入
插入其實跟檢索差不多,只不過找的合適的位置後要把元素插入進去。
用乙個引用記錄其父節點的lson或rson值,這樣就可以輕鬆插入了。
//更新節點資訊
void up(int
p) //
插入乙個關鍵碼為v的數
void insert(int &p, int
v)
if (v == bst[p].val) bst[p].cnt++;//
之前已經有v這個數了,直接次數+1
if (v > bst[p].val) insert(bst[p].ron, v);//
比他大,在他的右子樹里插
else insert(bst[p].lson, v);//
比他小,在他的左子樹里插
up(p);//
需要更新p的資訊(這裡是子樹大小)
}
up和線段樹類似,因為改變了p的兒子的資訊所以p的資訊肯定也要更改。
4,bst的後繼
首先檢索v,然後開始分類討論:
設v的節點編號為p。
i p有右子樹,則它的後繼一定在它的右子樹中否則它的右子樹將不是「它的右子樹」。
而且一定是它右孩子後一直往左孩子找。
ii 若p沒有右子樹,則它的後繼就是它的直系祖先中 > 它且最小的乙個(在檢索的時候記錄)
//找關鍵碼為v的後繼
int next(int
v)
break
; }
if (bst[p].val > v && (ret == -1 || bst[p].val < bst[ret].val)) ret = p, p = bst[p].lson;//
檢索時記錄
else p =bst[p].rson;
}return
ret;
//返回字尾的節點編號,若沒有返回-1(如在2,3,4中找5的字尾)
}
5,bst找前驅
更後繼差不多,不過是左子樹一直往右走,紀錄時也是《它最大的乙個。
//找關鍵碼為v的前驅
int pre(int
v)
break
; }
if (bst[p].val < v && (ret == -1 || bst[p].val > bst[ret].val)) ret = p, p = bst[p].rson;//
檢索時記錄
else p =bst[p].lson;
}return
ret;
//返回前驅的節點編號,若沒有返回-1(如在2,3,4中找1的前驅)
}
6,bst中刪除節點
首先也是先檢索它得到節點p
若v出現的大於1,那麼直接cnt--即可。
若p的子節點個數小於2,則直接刪除p,並令p的子節點代替p的位置,與p 的父節點相連。
若p既有左子樹又有右子樹,則在bst中求出v的後繼節點next。
因為next沒有左子樹(想想為什麼?),所以可以直接刪除next,並令next的右子樹代替next的位置。
最後, 再讓next節點代替p節點,刪除p即可。
void del(int &p, intv) else
if (!bst[p].rson) else
}up(p);
return
; }
if (bst[p].val else
del(bst[p].lson, v);
up(p);
}
update:
7,bst查詢排名
我們用迴圈的方式來求
對於當前節點p開始分類討論
(1)valp=v,ret+=p左子樹大小並退出迴圈
(2)valp
p及其左子樹均排在v前面,ret+=cntp+p左子樹的大小,跳p
(3)valp>v,此時ret並不能增加,直接跳p
//查詢v的排名
int rank(int
v)
if (v >bst[p].val)
else
}return ret + 1
;}
8,bst根據排名查詢數
有點類似主席樹,時間不早了,這就不講了
//查詢排名為k的數
int kth(int
k) k -=bst[p].cnt;
p =bst[p].rson;}}
return
ret;
}
update1:3-8
講真bst沒什麼n用,但它是學習平衡樹的基礎。
(資料結構)二叉查詢樹
樹,是一種資料結構。它是由n個有限節點組成乙個具有層次關係的集合。特點 樹的基本術語 節點的度 節點擁有的子樹的數目。葉子 度為零的節點。分支節點 度不為零的節點。樹的度 樹中節點的最大的度。層次 根節點的層次為1,其餘節點的層次等於該節點的雙親的層次加1。樹的高度 樹中節點的最大層次。無序樹 如果...
資料結構 二叉查詢樹
使二叉樹成為二叉查詢樹的性質是,對於樹中的每個節點x,它的左子樹中所有關鍵字值小於x的關鍵字值,而它的右子樹中所有關鍵字值大於x的關鍵字值。這意味著,該樹所有的元素以某種統一的方式排序。二叉查詢樹是一棵特殊的二叉樹,二叉查詢樹中節點的結構與二叉樹種節點的結構相同,關鍵在於可以在二叉查詢樹上可以執行的...
資料結構 樹 二叉查詢樹
wiki 首先是名稱 二叉查詢樹英文叫binary search tree,這個在很多演算法題目中很常見所以要記住,特別是英文題目中。也叫做二叉排序樹,二叉搜尋樹等等。具體的定義比較官方,用自己的話說,首先它肯定是二叉樹,其次,當前節點的左子葉元素值比當前節點小,右子葉元素值比當前節點大,所以節點均...