二叉搜尋樹(二叉排序樹)
阿新 • • 發佈:2019-02-15
內容和程式碼參考殷人昆版的《資料結構》
二叉搜尋樹也稱為二叉排序樹,二叉搜尋樹要麼是空樹,要麼具有如下性質:
(1)每個結點都有一個作為搜尋依據的結點值,並且每個結點值互不相同;
(2)左子樹(如果存在)上的所有結點值都小於根結點的值;
(3)右子樹(如果存在)上的所有結點值都大於根結點的值;
(4)左子樹和右子樹也是二叉搜尋樹。
對一棵二叉搜尋樹進行中序遍歷,可以從小到大的將結點值排列起來。這裡注意的是:同一組資料根據不同的排列可以構建出多棵不同的二叉搜尋樹。對於有n個關鍵碼的集合,有n!中不同的排列,可以構成種不同的二叉搜尋樹。
二叉搜尋樹搜尋、插入、刪除操作的平均時間代價為O(logn).
二叉搜尋樹的結構體定義:
//結構體的類定義
template<class T>
struct BSTree{
T data;
BSTree* left, right;
BSTree():left(NULL),right(NULL){};
};
二叉搜尋樹的查詢:(注意:我看其他的資料程式碼,有的查詢操作返回的是void,如果返回void就不能知道是否返回成功;查詢操作應該返回的查詢到的樹結點)
//查詢
template<class T>
BSTree* search(const T x, BSTree* ptr){
if(ptr == NULL)return NULL; //搜尋失敗
else if(x < ptr->data)search(x, ptr->left);
else if(x > ptr->data)search(x, ptr->right);
else return ptr; //搜尋成功
}
二叉搜尋樹的插入:(注意:向二叉搜尋樹中插入一個元素,必須先檢查這個元素是否在樹中已經存在)
//插入
template<class T>
bool insert(const T x, BSTree* & ptr){
if(ptr == NULL){ //新結點作為葉結點插入
ptr = new BSTree(x); //建立新的結點
if(ptr == NULL){cerr<<"out of space"<<endl; exit(-1)};
return true;
}
else if(x < ptr->data)insert(x,ptr->left); //向左子樹搜尋
else if(x > ptr->data)insert(x,ptr->right); //向右子樹搜尋
else return false; //這個表明要插入的元素在樹中已經存在,返回false
}
二叉搜尋樹的刪除:(二叉搜尋樹的刪除有三種情況:1、結點的右子樹為空,則用左子樹填補;2、結點的左子樹為空,則用右子樹填補;3、結點的左右子樹都不為空,則在它的右子樹中序遍歷下的第一個結點來填補,然後遞迴地處理右子樹)
//刪除
template<class T>
bool remove(const T x, BSTree* & ptr){
BSTree* temp;
if(ptr != NULL){
if(x < ptr->data)remove(x,ptr->left);
else if(x > ptr->data)remove(x, ptr->right);
else if(ptr->left != NULL && ptr->right != NULL){ //左右子樹均不為空
temp = ptr->right;
while(temp->left != NULL)temp = temp->left; //用它的右子樹中序遍歷下的第一個結點來填補
ptr->data = temp->data;
remove(ptr->data, ptr->right); //然後要刪除被拿來填補的那個結點,遞迴的處理右子樹
}
else{
temp = ptr;
if(ptr->left == NULL)ptr = ptr->right;
else ptr = ptr->left;
delete temp;
return true;
}
}
reurn false;
}
以上的操作都用遞迴的方式實現,我覺得遞迴的方式效率雖然不高,但看起來真的很舒服啊=_=,所以就直接用遞迴的方式了,以後有時間再用非遞迴的方式實現一遍。