資料結構: 二叉搜尋樹
阿新 • • 發佈:2018-12-25
二叉搜尋樹
二叉查詢樹(Binary Search Tree),也稱二叉搜尋樹、有序二叉樹(ordered binary tree),排序二叉樹(orted binary tree)
特點:
- 二叉樹
- 若任意節點的左子樹不空,則左子樹上所有節點的值均小於它的根節點的值
- 若任意節點的右子樹不空,則右子樹上所有節點的值均大於它的根節點的值
- 任意節點的左,右子樹也分別為二叉查詢樹
- 沒有鍵值相等的節點
注:
堆
必須是完全二叉樹- 二叉搜尋樹不一定是完全二叉樹
優勢
二叉搜尋相比其他資料結構在查詢和插入的複雜度較低. 均為 O(logN).
它是基礎的資料結構,可用於構建更抽象的資料結構,如集合,對映等.
常用操作
0. 定義:
用一個根節點表示一個二叉搜尋樹
節點的結構如下所示:
template<typename Key,typename Value> class BST { private: struct Node { Key key; Value value; Node *left; Node *right; Node(key key, Value value) { this->key = key; this->value = value; this->left = this->right = NULL; } }; Node *root; int count; public: BST() { root = NULL; count = 0; } ~BST() { // TODO: } }
1. 查詢
在二叉搜尋樹 root
中查詢 key
是否存在
bool contains(Node* node, Key key) { if (node == NULL) return NULL; if (node->key > key) { return contains(node->left, key); } else if (node->key < key) { return contains(node->right, key); } else { return true; } }
2.插入
插入和查詢是一樣的
// 將(key,value)插入二叉搜尋樹中,返回根節點
Node* insert(Key key,Value value) {
root = insert(root, key,value);
return root;
}
Node* insert(Node *node, Key key, Value value) {
if (node == NULL) {
count++;
root = new Node(key, value);
} else {
if (key == node->key) {
node->value = value;
}
else if (key > node->key) {
node->right = insert(node->right,key,value);
}
else{
// key < node->key
node->left = insert(node->left, key, value);
}
}
return node;
}
3. 刪除
刪除分為3種情況:
- 只有左孩子,則將左孩子返回
- 只有右孩子,則將右孩子返回
- 左右孩子都有,找到這個節點的後繼節點,再刪除右子樹中的最小節點.將後繼節點的左孩子指向當前的左孩子.然後返回後繼節點.
// 將關鍵字為key的節點,返回根節點
Node* delete(Key key) {
root = delete(root, key);
}
//
Node* delete(Node* node, Key key) {
if (node == NULL) {
return NULL;
}
if (node->key < key) {
// 在左子樹中刪除,返回根節點的左孩子
node->left = delete(node->left, key);
return node;
}
else if (node->key > key) {
// 在右子樹中刪除,返回根節點的右孩子
node->right = delete(node->right, key);
return node;
}
else {// 找到了該節點
// 若左孩子為空,那麼則返回其右孩子
if (node->left == NULL) {
Node* rightNode = node->right;
node->right = NULL;
size--;
return rightNode;
}
// 若右孩子為空,那麼則返回其左孩子
else if (node->right == NULL) {
Node* leftNode = node->left;
node->left = NULL;
size--;
return leftNode;
}
else {
// 如果二者都不為空,在右子樹找最小值結點,即後繼節點
Node* successor = minimum(node->right);
// 將這個最小值結點刪除
successor->right = deleteMin(node->right);
// 將原來節點的左子樹付給它
successor->left = node->left;
// 刪除Node
node->left = node->right = NULL;
// 返回這個節點
return successor;
}
}
}
// 遞迴找最小值節點
Node* minimum(Node* node) {
if (node->left == NULL){
return node;
}
return minimum(node->left);
}
// 遞迴找最大值節點
Node* Maximum(Node* node) {
if (node->right == NULL) {
return node;
}
return Maximum(node->right);
}
Node* deleteMin(Node* node) {
if (node->left == NULL) {
Node* rightNode = node->right;
node->right = NULL;
size--;
return rightNode;
}
node->left = deleteMin(node->left);
return node;
}
Node* deleteMax(Node* node) {
if (node->right == NULL) {
Node* leftNode = node->left;
node->left = NULL;
size--;
return leftNode;
}
node->right = deleteMin(node->right);
return node;
}
4.遍歷
中序遍歷有序