【基礎知識】 之 Binary Search Tree 二叉搜索樹

原文地址爲:【基礎知識】 之 Binary Search Tree 二叉搜索樹

前言

這個系列是畢業找工作的複習筆記,希望可以和廣大正準備畢業的童鞋一起打牢基礎,迎接各種筆試……爲了應付中英文筆試,關鍵詞都用英文進行標註,這樣就不怕面對英文題目了。之所以開始這一系列是因爲之前在參加微軟筆試的時候,被一道stable sorting的選擇題給卡住了,才發現自己的基本功什麼時候變得這麼差了。既然要找工作就要好好複習,從最基礎的開始。算法的部分來自《The Algorithm Design Manual》的筆記。

結構特點

二叉搜索樹的特點是,小的值在左邊,大的值在右邊,即

比如:

這樣的結構有一個好處是很容易獲得最大值(Maximum)、最小值(minimum)、某元素的前驅(Precursor)、某元素的後繼(Successor)。

最大值:樹的最右節點。

最小值:樹的最左節點。

某元素前驅:左子樹的最右。

某元素的後繼:右子樹的最左。

基本操作

二叉搜索樹的基本操作包括searching、traversal、insertion以及deletion。

(代碼爲了省地方沒有按照規範來寫,真正寫代碼的時候請一定遵照規範)

① searching

tree * search_tree(tree *l, item_type x){
if(l == null) return NULL;
if(l->item == x) return l;
if(x < l->item){
return (search_tree(l->left, x));
}
if(x > l->item){
return (search_tree(l->right, x));
}
}

時間複雜度爲O(h),h爲樹的高度。

② traversal

由於小的節點在左邊,大的節點在右邊,因此使用中序(in-order)遍歷可以方便的得到一個sorted list。

void traverse_tree(tree *l){
if(l != NULL){
traverse_tree(l
->left);
process_item(l
->item);
traverse_tree(l
->right);
}
}

時間複雜度爲O(n),n爲樹的總結點數。

③ insertion

insert_tree(tree **l, item_type x, tree *parent){
tree
*p; /*temporary pointer*/
if(*l == NULL){
p
= malloc(sizeof(tree));
p
->item = x;
p
->left = p->right = NULL;
p
->parent = parent;
*l = p;
return;
}
if(x < (*l)->item){
insert_tree(
&((*l)->left), x, *l);
}
else{
insert_tree(
&((*l)->right), x, *l);
}
}

時間複雜度爲O(h),h爲樹的高度。

④deletion

在刪除節點時有三種情況:

1)要刪除的節點爲葉節點

  那麼直接刪除即可。

2)要刪除的節點有一個子節點

  那麼刪除掉該節點,並用其唯一的子節點代替自己的位置即可。

3)要刪除的節點有兩個子節點

  那麼首先要找到該節點的右子樹的最小值節點k,然後將該k替換掉待刪除節點。

最壞情況下,時間複雜度爲O(h)+指針的移動開銷。

 

進階

由上可知,二叉搜索樹的dictionary operation(包括search、insertion、deletion)的時間複雜度均與O(h)相關,h爲樹的高度(log n),如果按照上述的insertion方法構建樹,那麼構建出來的樹的形狀各異,特別是當輸入序列有序時,更會退化到鏈表的程度。所以,如果能用某種方法,將樹的高度降低到最小,那麼其dictionary operation的時間開銷均可以降低,不過相對而言構建樹的開銷將增大。爲了降低二叉搜索樹的高度而提出了平衡二叉樹(Balanced Binary Tree)的概念。它要求左右兩個子樹的高度差的絕對值不超過1,並且左右兩個子樹都是一棵平衡二叉樹。這樣就可以將搜索樹的高度儘量減小。常用算法有紅黑樹、AVL、Treap、伸展樹等。

 


轉載請註明本文地址:【基礎知識】 之 Binary Search Tree 二叉搜索樹
發佈了0 篇原創文章 · 獲贊 104 · 訪問量 78萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章