二分搜索树最难的操作是remove,floor,ceil,需要多看。
BST.h
#pragma once
#include<iostream>
#include<queue>
#include<cassert>
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 = 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);
}
//void insert(Key key, Value value)//非递归写法:双指针法
//{
// Node * pnode = root;//指向应该插入的位置
// Node * pre = pnode;//指向应该插入位置的父亲节点
// //找到应该插入的位置
// while (pnode != NULL)
// {
// if (pnode->key == key)//如果插入的key节点已存在,则替换掉value值即可
// {
// pnode->value = value;
// return;
// }
// else if (pnode->key > key)
// {
// pre = pnode;
// pnode = pnode->left;
// }
// else
// {
// pre = pnode;
// pnode = pnode->right;
// }
// }
//
// pnode = new Node(key, value);//新建一个节点
// //如果没有根节点,则创造一个
// if (pre == NULL)
// root = pnode;
// //以下两行代表将新建的节点连接上父亲节点
// else if (pre->key > pnode->key)
// pre->left = pnode;
// else
// pre->right = pnode;
// count++;
//}
bool contain(Key key)
{
return contain(root, key);
}
Value * search(Key key)//返回Value*的好处是,当查找失败时可以返回NULL
{
return search(root, key);
}
void preOrder()
{
preOrder(root);
}
void inOrder()
{
inOrder(root);
}
void postOrder()
{
postOrder(root);
}
void leverOrder()//利用队列进行层序遍历
{
queue<Node *> q;
q.push(root);
while (!q.empty())
{
Node * node = q.front();
q.pop();
cout << node->value << endl;
if (node->left != NULL)
q.push(node->left);
if (node->right != NULL)
q.push(node->right);
}
}
//寻找最小的键值:非递归写法
Key minimum()
{
assert(count != 0);
Node * node = root;
while (node->left != NULL)
node = node->left;
return node->key;
}
//寻找最大键值:非递归写法
Key maximum()
{
assert(count != 0);
Node * node = root;
while (node->right != NULL)
node = node->right;
return node->key;
}
void removeMin()
{
if (root == NULL) return;
Node * cur = root;//最小键值节点
Node * pre = cur;//最小键值节点的父节点
while (cur->left != NULL)
{
pre = cur;
cur = cur->left;
}
if (cur == pre)//如果根节点没有左孩子,此时cur与pre都指向root,root为最小键值节点,将根节点指向当前右孩子即可
root = cur->right;
else if (cur->right == NULL)//如果最小键值节点没有右孩子,直接删除即可
pre->left = NULL;//这句不可删,否则pre->left会是乱码
else//如果最小键值有右孩子,则将pre节点的左孩子直接连接上这个右孩子,即可维护二分搜索树的性质
pre->left = cur->right;
delete cur;
count--;
}
void removeMax()
{
if (root == NULL) return;
Node * cur = root;//最大键值节点
Node * pre = cur;//最大键值节点的父节点
while (cur->right != NULL)
{
pre = cur;
cur = cur->right;
}
if (cur == pre)//如果根节点没有右孩子,此时cur与pre都指向root,root为最大键值节点,将根节点指向当前左孩子即可
root = cur->right;
else if (cur->left == NULL)//如果最大键值节点没有左孩子,直接删除即可
pre->right = NULL;//这句不可删,否则pre->right会是乱码
else//如果最小键值有左孩子,则将pre节点的右孩子直接连接上这个左孩子,即可维护二分搜索树的性质
pre->right = cur->left;
delete cur;
count--;
}
void remove(Key key)//较困难,需要多看几遍!!!
{
root = remove(root, key);
}
// 寻找key的floor值, 递归算法
// 如果不存在key的floor值(key比BST中的最小值还小), 返回NULL
Key * floor(Key key)
{
if (count == 0 || key < minimum())
return NULL;
Node * floorNode = floor(root, key);
return &(floorNode->key);
}
// 寻找key的ceil值, 递归算法
// 如果不存在key的ceil值(key比BST中的最大值还大), 返回NULL
Key* ceil(Key key) {
if (count == 0 || key > maximum())
return NULL;
Node *ceilNode = ceil(root, key);
return &(ceilNode->key);
}
private:
// 在以node为根的二叉搜索树中, 寻找key的floor值所处的节点, 递归算法
Node * floor(Node * node, Key key)
{
if (node == NULL)
return NULL;
// 如果node的key值和要寻找的key值相等
// 则node本身就是key的floor节点
if (node->key == key)
return node;
// 如果node的key值比要寻找的key值大
// 则要寻找的key的floor节点一定在node的左子树中
if (node->key > key)
return floor(node->left, key);
// 如果node->key < key
// 则node有可能是key的floor节点, 也有可能不是(存在比node->key大但是小于key的其余节点)
// 需要尝试向node的右子树寻找一下
Node * tempNode = floor(node->right, key);
if (tempNode != NULL)
return tempNode;
return node;
}
// 在以node为根的二叉搜索树中, 寻找key的ceil值所处的节点, 递归算法
Node* ceil(Node* node, Key key) {
if (node == NULL)
return NULL;
// 如果node的key值和要寻找的key值相等
// 则node本身就是key的ceil节点
if (node->key == key)
return node;
// 如果node的key值比要寻找的key值小
// 则要寻找的key的ceil节点一定在node的右子树中
if (node->key < key)
return ceil(node->right, key);
// 如果node->key > key
// 则node有可能是key的ceil节点, 也有可能不是(存在比node->key小但是大于key的其余节点)
// 需要尝试向node的左子树寻找一下
Node* tempNode = ceil(node->left, key);
if (tempNode != NULL)
return tempNode;
return node;
}
Node * remove(Node * node, Key key)
{
if (node == NULL)
return NULL;
if (node->key > key)
{
node->left = remove(node->left, key);
return node;
}
else if (node->key < key)
{
node->right = remove(node->right, key);
return node;
}
else //node->key == 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;
}
}
void destroy(Node * node)
{
if (node != NULL)
{
destroy(node->left);
destroy(node->right);
delete node;
count--;
}
}
//对以node为根的二叉搜索树进行后序遍历
void postOrder(Node * node)
{
if (node != NULL)
{
postOrder(node->left);
postOrder(node->right);
cout << node->key << endl;
}
}
//对以node为根的二叉搜索树进行中序遍历
void inOrder(Node * node)
{
if (node != NULL)
{
inOrder(node->left);
cout << node->key << endl;
inOrder(node->right);
}
}
//对以node为根的二叉搜索树进行前序遍历
void preOrder(Node * node)
{
if (node != NULL)
{
cout << node->key << endl;
preOrder(node->left);
preOrder(node->right);
}
}
//在以node为根的二叉搜索树中查找key所对应的value
Value * search(Node * node, Key key)
{
if (node->key == NULL)
return NULL;
if (node->key == key)
return &node->value;
else if (node->key > key)
return search(node->left, key);
else //node->key < key
return search(node->right, key);
}
//查看以node为根的二叉搜索树中是否包含键值为key的节点
bool contain(Node * node, Key key)
{
if (node->key == NULL)
return false;
if (node->key == key)
return true;
else if (node->key > key)
return contain(node->left, key);
else //node->key < key
return contain(node->right, key);
}
//向以node为根的二叉搜索树中,插入节点(key,value)
//返回插入新节点后的二叉搜索树的根
Node * insert(Node *node, Key key, Value value)
{
if (node == NULL)
{
count++;
return new Node(key, value);
}
if (node->key == key)
node->value = value;
else if (key < node->key)
node->left = insert(node->left, key, value);
else //key > node->key
node->right = insert(node->right, key, value);
return node;
}
};main.cpp
#include<iostream>
#include<time.h>
#include"BST.h"
using namespace std;
int main()
{
BST<int,int> bst;
srand((unsigned)time(NULL));
int nums = 15;
while (nums--)
{
int i = rand() % 100;
bst.insert(i, i);
}
//bst.insert(5, 5);
//bst.insert(7, 7);
//bst.insert(6, 6);
//bst.insert(8, 8);
bst.inOrder();
cout << "minmum:" << bst.minimum() << endl;
cout << "maxmum:" << bst.maximum() << endl;
bst.removeMin();
bst.removeMax();
bst.inOrder();
cout << "minmum:" << bst.minimum() << endl;
cout << "maxmum:" << bst.maximum() << endl;
return 0;
}
903

被折叠的 条评论
为什么被折叠?



