Created
October 7, 2018 06:41
-
-
Save dongyuanxin/d0803a8821c6797e9ce8522a676cf44b to your computer and use it in GitHub Desktop.
Binary Search Tree
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
// | |
// Created by godbmw.com on 2018/9/27. | |
// | |
#ifndef BINARYSEARCH_BST_H | |
#define BINARYSEARCH_BST_H | |
#include <iostream> | |
#include <queue> | |
using namespace std; | |
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 = NULL; | |
this->right = NULL; | |
} | |
Node(Node* node) { | |
this->key = node->key; | |
this->value = node->value; | |
this->left = node->left; | |
this->right = node->right; | |
} | |
}; | |
Node *root; | |
int count; | |
private: | |
Node* insert(Node* node, Key key, Value value) { | |
if(node == NULL) { | |
count++; | |
return new Node(key, value); | |
} | |
if(key == node->key) { | |
node->value = value; | |
} else if( key < node->key) { | |
node->left = insert(node->left, key, value); | |
} else { | |
node->right = insert(node->right, key, value); | |
} | |
return node; | |
} | |
bool contain(Node* node, Key key) { | |
if(node == NULL) { | |
return false; | |
} | |
if(key == node->key) { | |
return true; | |
} else if(key < node->key) { | |
return contain(node->left, key); | |
} else { | |
return contain(node->right, key); | |
} | |
} | |
Value* search(Node* node, Key key) { | |
if(node == NULL) { | |
return NULL; | |
} | |
if(key == node->key) { | |
return &(node->value); | |
} else if (key < node->key) { | |
return search(node->left, key); | |
} else { | |
return search(node->right, key); | |
} | |
} | |
void pre_order(Node* node) { | |
if(node != NULL) { | |
cout<<node->key<<endl; | |
pre_order(node->left); | |
pre_order(node->right); | |
} | |
} | |
void in_order(Node* node) { | |
if(node != NULL) { | |
in_order(node->left); | |
cout<<node->key<<endl; | |
in_order(node->right); | |
} | |
} | |
void post_order(Node *node) { | |
if(node != NULL) { | |
post_order(node->left); | |
post_order(node->right); | |
cout<<node->key<<endl; | |
} | |
} | |
// 和后序遍历相似:先destroy左右节点,再释放节点自身 | |
void destroy(Node *node) { | |
if(node != NULL) { | |
destroy(node->left); | |
destroy(node->right); | |
delete node; | |
// 别忘记count变动 | |
this->count--; | |
} | |
} | |
// 层序遍历 | |
void level_order(Node* node) { | |
if(node == NULL) { | |
return; | |
} | |
queue<Node*> q; | |
q.push(node); | |
while(!q.empty()) { | |
Node* node = q.front(); | |
q.pop(); | |
cout<< node->key <<endl; | |
if(node->left) { | |
q.push(node->left); | |
} | |
if(node->right) { | |
q.push(node->right); | |
} | |
} | |
} | |
// 寻找最小键值 | |
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* remove_min(Node* node) { | |
if(node->left == NULL) { | |
Node* right = node->right; | |
delete node; | |
count--; | |
return right; | |
} | |
node->left = remove_min(node->left); | |
return node; | |
} | |
Node* remove_max(Node* node) { | |
if(node->right == NULL) { | |
Node* left = node->left; | |
delete node; | |
count--; | |
return left; | |
} | |
node->right = remove_max(node->right); | |
return node; | |
} | |
// 删除掉以node为根的二分搜索树中键值为key的节点 | |
// 返回删除节点后新的二分搜索树的根 | |
// 时间复杂度: O(logN) | |
Node* remove(Node* node, Key key) { | |
if(node == NULL) { | |
return NULL; | |
} | |
if(key < node->key) { | |
node->left = remove(node->left, key); | |
} else if(key > node->key){ | |
node->right = remove(node->right, key); | |
} else { | |
// key == node->key | |
if(node->left == NULL) { | |
Node* right = node->right; | |
delete node; | |
count--; | |
return right; | |
} | |
if(node->right == NULL) { | |
Node *left = node->left; | |
delete node; | |
count--; | |
return left; | |
} | |
// node->right != NULL && node->left != NULL | |
Node* successor = new Node(minimum(node->right)); | |
count++; | |
// "count --" in "function remove_min(node->right)" | |
successor->right = remove_min(node->right); | |
successor->left = node->left; | |
delete node; | |
count--; | |
return successor; | |
} | |
return node; | |
} | |
Node* floor(Node* node, Key key) { | |
if(node == NULL) { | |
return NULL; | |
} | |
// key等于node->key:floor的结果就是node本身 | |
if(node->key == key) { | |
return node; | |
} | |
// key小于node—>key:floor的结果肯定在node节点的左子树 | |
if(node->key > key) { | |
return floor(node->left, key); | |
} | |
// key大于node->key:右子树可能存在比node->key大,但是比key小的节点 | |
// 如果存在上述情况,返回这个被选出来的节点 | |
// 否则,函数最后返回node本身 | |
Node* tmp = floor(node->right, key); | |
if(tmp != NULL) { | |
return tmp; | |
} | |
return node; | |
} | |
Node* ceil(Node* node, Key key) { | |
if(node == NULL) { | |
return NULL; | |
} | |
if(node->key == key) { | |
return node; | |
} | |
if(node->key < key) { | |
return ceil(node->right, key); | |
} | |
Node* tmp = ceil(node->left, key); | |
if(tmp != NULL) { | |
return tmp; | |
} | |
return node; | |
} | |
public: | |
BST() { | |
this->root = NULL; | |
this->count = 0; | |
} | |
~BST() { | |
this->destroy(this->root); | |
} | |
int size() { | |
return this->count; | |
} | |
bool isEmpty() { | |
return this->root == NULL; | |
} | |
void insert(Key key, Value value) { | |
this->root = this->insert(this->root, key, value); | |
} | |
bool contain(Key key) { | |
return this->contain(this->root, key); | |
} | |
// 注意返回值类型 | |
Value* search(Key key) { | |
return this->search(this->root, key); | |
} | |
void pre_order() { | |
this->pre_order(this->root); | |
} | |
void in_order() { | |
this->in_order(this->root); | |
} | |
void post_order() { | |
this->post_order(this->root); | |
} | |
void level_order() { | |
this->level_order(this->root); | |
} | |
// 寻找最小键值 | |
Key* minimum() { | |
if(this->count == 0) return NULL; | |
Node* min_node = this->minimum(this->root); | |
return &(min_node->key); | |
} | |
// 寻找最大键值 | |
Key* maximum() { | |
if(this->count == 0) return NULL; | |
Node* max_node = this->maximum(this->root); | |
return &(max_node->key); | |
} | |
void remove_min() { | |
if(this->root == NULL) { | |
return; | |
} | |
this->root = this->remove_min(this->root); | |
} | |
void remove_max() { | |
if(this->root == NULL) { | |
return; | |
} | |
this->root = this->remove_max(this->root); | |
} | |
void remove(Key key) { | |
this->root = remove(this->root, key); | |
} | |
Key* floor(Key key) { | |
Key* min_key = this->minimum(); | |
if(this->isEmpty() || key < *min_key) { | |
return NULL; | |
} | |
// floor node | |
Node *node = floor(this->root, key); | |
return &(node->key); | |
} | |
Key* ceil(Key key) { | |
Key* max_key = this->maximum(); | |
if(this->isEmpty() || key > *max_key) { | |
return NULL; | |
} | |
// ceil node | |
Node* node = ceil(this->root, key); | |
return &(node->key); | |
} | |
}; | |
#endif //BINARYSEARCH_BST_H |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment