二分搜索树的基本操作
二分搜索树的优势:
能够高效、动态维护数据,还可以很方便的回答很多数据关系的问题,比如min、max、floor、ceil、rank、select等。
[定义]
二分搜索树的特点如下:
1、二分搜索树是一棵二叉树
2、每个节点的键值大于左子树中所有节点
3、每个节点的键值小于右子树中所有节点
4、以左右孩子为根的子树仍为二分搜索树
二分搜索树没有完全二叉树的要求,不一定是完全二叉树**
#include<queue>
#include<cassert>
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(Node *node){
this->key = node->key;
this->value = node->value;
this->left = node->left;
this->right = node->right;
}
};
Node *root;
int count;
public:
BST(){
root = NULL;
count = 0;
}
~BST(){
destroy(root);
}
int size(){
return count;
}
bool isEmpty(){
return count == 0;
}
void insert(Key key,Value value){
root = insert(root,key,value);
bool contain(Key key){
return contain(root,key,value);
}
}
Value* search(Key key){
return search(root,key);
}
//前序遍历
void preOrder(){
preOrder(root);
}
//中序遍历
void inOrder(){
inOrder(root);
}
//后序遍历
void postOrder(){
postOrder(root);
}
//层次遍历
void levelOreder(){
queue<Node*> q;
q.push(root);
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);
}
}
//寻找最小的键值
Key minimum(){
assert(count != 0);
Node* minNode = minimum(root);
return minNode->key;
}
//寻找最大的键值
Key maximum(){
assert(count != 0);
Node* maxNode = maximum(root);
return maxNode->key;
}
//从二叉树中删除最小值所在节点
void removeMin(){
if(root)
root = removeMin(root);
}
//从二叉树中删除最大值所在节点
void removeMan(){
if(root)
root = removeMan(root);
}
//从二叉树中删除键值为key的节点
void removeMax(){
root=remove(root,key);
}
private:
//向以node为根的二叉搜索树中,插入节点(key ,value)
//返回插入新节点后的二叉搜索树的根
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 //key>node->key
node->ringht = insert(node->right,key,value);
return node;
}
//查看以node为根的二叉搜索树中是否包含键值为key的节点
bool contain(Node* node,Key key){
if(node == NULL)
return false;
if(key == node->key)
return ture;
else if(key < nodde->key)
return contain(node->left,key);
else //key>node->key
return contain(node->right,key);
}
Value* search(Node* node,Key key){
if(node == NULL)
return NULL;
if(key==node->key)
return search(node->left,key);
else if(key < node->key)
return search(node->right,key);
}
//对以node为根的二叉搜索树进行前序遍历
void preOrder(Node* node){
if(node != NULL){
count<<node->key<<endl;
preOrder(node->left);
preOrder(node->ringht);
}
}
//对以node为根的二叉搜索树进行中序遍历
void inOrder(Node* node){
if(node != NULL)
{
if(node != NULL){
inOrder(node->left);
cout<<node->key<<endl;
inorder(node->right);
}
}
}
//对以node为根的二叉搜索树进行后序遍历
void postOrder(Node* node){
if(node != NULL){
postOrder(node->left);
postOrder(node->right);
cout<<node->key<<endl;
}
}
void destroy(Node* node){
if(node != NULL){
destroy(node->left);
destroy(node->right);
delete node;
count--;
}
}
//在以node为根的二叉搜索树中,返回最小键值的节点
Node* minimum(Node* node){
if(node->left == NULL)
return node;
return minimum(node->left);
}
//在以node为根的二叉搜索树中,返回最大键值的节点
Node* maximum(Node* node){
if(node->right == NULL)
return node;
return maximum(node->right);
}
//删除掉以node为根的二分搜索树中的最小节点
//返回删除节点后新的二分搜索树的根
Node* removeMin(Node* node){
if(node->left == NULL){
Node* rightNode = node->right;
delete node;
count--;
return rightNode;
}
node->left = removeMin(node->left);
return node;
}
//删除掉以node为根的二分搜索树中的最大节点
//返回删除节点后新的二分搜索树的根
Node* removeMax(Node* node){
if(node->right == NULL){
Node* leftNode = node->left;
delete node;
count--;
return leftNode;
}
node->right = removeMan(node->right);
return node;
}
//删除掉以node为根的二分搜索树中键值为key的节点
//返回删除节点后新的二分搜索树的根
Node* remove(Node* node,Key key){
if(node == NULL)
return NULL;
if(key<node->key){
node->left = remove(node->left,key);
return node;
}
else if(key > node->key){
node->right = remove(node->right,key);
return node;
}
else{//key == node->key
if(node->left == NULL){
Node *rightNode = node->right;
delete node;
count--;
return rightNode;
}
if(node->right == NULL){
Node *leftNode = node->left;
delete node;
count--;
return leftNode;
}
//node->left != NULL && node->right != NULL
Node *successor = new Node(minimum(node->right));
count++;
successor->right = removeMin(node->right);
successor->left = node->left;
delete node;
count--;
return successor;
}
}
};