二叉搜尋樹-map/set的底層容器(C++實現)
阿新 • • 發佈:2020-12-17
為了聚焦於二叉搜尋樹演算法的實現,沒有采用模板支援不同資料型別,(key, value)均採用 int 數值。
節點定義
struct Node { int key = 0; int value = 0; Node *left = nullptr; Node *right = nullptr; Node() : key(0), value(0), left(nullptr), right(nullptr) {} Node(int k, int v) : key(k), value(v), left(nullptr), right(nullptr) {} Node(Node *rhs) : key(rhs->key), value(rhs->value), left(rhs->left), right(rhs->right) {} Node(int k, int v, Node *left, Node *right) : key(k), value(v), left(left), right(right) {} };
二叉搜尋樹定義
class BST { public: BST() {} BST(Node *p, int size) : root(p), count(size) {} void insert(int k, int v); int *search(int k); bool contain(int k); // 深度遍歷 void preOrder(); void inOrder(); void postOrder(); // 廣度遍歷 void levelOrder(); // 最大最小值 int maxinum(); int mininum(); void removeMax(); void removeMin(); // 刪除任意節點 void removeNode(int key); // floor/ceil int *floor(int key); int *ceil(int key); private: Node *floor(Node *p, int key); Node *ceil(Node *p, int key); Node *removeNode(Node *p, int key); Node *maxinum(Node *p); Node *mininum(Node *p); Node *removeMax(Node *p); Node *removeMin(Node *p); Node *insert(Node *p, int k, int v); int *search(Node *p, int k); bool contain(Node *p, int k); void preOrder(Node *p); void inOrder(Node *p); void postOrder(Node *p); void levelOrder(Node *p); Node *root = nullptr; int count = 0; };
插入
void BST::insert(int k, int v) { root = insert(root, k, v); } Node *BST::insert(Node *node, int k, int v) { if (node == nullptr) { ++count; // attention return new Node(k, v); } if (k < node->key) { node->left = insert(node->left, k, v); } else if (k > node->key) { node->right = insert(node->right, k, v); } else { node->value = v; } return node; }
查詢/是否包含
int *BST::search(int k) {
return search(root, k);
}
int *BST::search(Node *p, int k) {
if (p == nullptr) {
return nullptr;
}
if (k == p->key) {
return &(p->value);
} else if (k < p->key) {
return search(p->left, k);
} else {
return search(p->right, k);
}
}
bool BST::contain(int k) {
return contain(root, k);
}
bool BST::contain(Node *p, int k) {
if (!p) {
return false;
}
if (k == p->key) {
return true;
} else if (k < p->key) {
return contain(p->left, k);
} else {
return contain(p->right, k);
}
}
深度遍歷
void BST::preOrder() {
preOrder(root);
}
void BST::inOrder() {
inOrder(root);
}
void BST::postOrder() {
postOrder(root);
}
void BST::preOrder(Node *p) {
if (p) {
std::cout << p->key << "->" << p->value << " ";
preOrder(p->left);
preOrder(p->right);
}
}
void BST::inOrder(Node *p) {
if (p) {
inOrder(p->left);
std::cout << p->key << "->" << p->value << " ";
inOrder(p->right);
}
}
void BST::postOrder(Node *p) {
if (p) {
postOrder(p->left);
postOrder(p->right);
std::cout << p->key << "->" << p->value << " ";
}
}
廣度遍歷
void BST::levelOrder() {
levelOrder(root);
}
void BST::levelOrder(Node *p) {
if (!p) {
return;
}
std::queue<Node *> q;
q.push(p);
while (!q.empty()) {
auto node = q.front();
std::cout << node->key << "->" << node->value << " ";
q.pop();
if (node->left) {
q.push(node->left);
}
if (node->right) {
q.push(node->right);
}
}
}
獲取最大/最小節點
int BST::maxinum() {
assert(count > 0);
Node *node = maxinum(root);
return node->key;
}
int BST::mininum() {
assert(count > 0);
Node *node = mininum(root);
return node->key;
}
Node *BST::maxinum(Node *p) {
auto node = p;
while (node->right) {
node = node->right;
}
return node;
}
Node *BST::mininum(Node *p) {
auto node = p;
while (node->left) {
node = node->left;
}
return node;
}
刪除最大/最小節點
void BST::removeMax() {
if (root) {
root = removeMax(root);
}
}
void BST::removeMin() {
if (root) {
root = removeMin(root);
}
}
Node *BST::removeMax(Node *p) {
// 迭代實現
if (p->right == nullptr) {
// 根節點無右子樹
Node *lnode = p->left;
delete p;
return lnode;
}
// 迭代到待刪除最小節點
auto p1 = p;
auto p2 = p->right;
while (p2->right) {
p1 = p2;
p2 = p2->right;
}
p1->right = p2->left; // 最大節點可能還有左子節點
delete p2;
--count;
return p;
}
Node *BST::removeMin(Node *p) {
// 迭代實現
if (p->left == nullptr) {
// 根節點無左子樹
Node *rnode = p->right;
delete p;
return rnode;
}
// 迭代到待刪除最小節點
auto p1 = p;
auto p2 = p->left;
while (p2->left) {
p1 = p2;
p2 = p2->left;
}
p1->left = p2->right; // 最小節點可能還有右子節點
delete p2;
--count;
return p;
}
刪除任意節點
// 刪除任意節點
void BST::removeNode(int key) {
if (contain(key)) {
root = removeNode(root, key);
}
}
Node *BST::removeNode(Node *p, int key) {
if (key < p->key) {
p->left = removeNode(p->left, key);
return p;
} else if (key > p->key) {
p->right = removeNode(p->right, key);
return p;
} else {
if (p->left == nullptr) {
auto res = p->right;
delete p;
return res;
} else if (p->right == nullptr) {
auto res = p->left;
delete p;
return res;
} else {
auto minNode = mininum(p->right);
Node *newNode = new Node(minNode->key, minNode->value);
newNode->left = p->left;
newNode->right = removeMin(p->right);
return newNode;
}
}
}
floor/ceil
// floor/ceil
int *BST::floor(int key) {
if (count == 0 || key < mininum()) {
return nullptr;
}
Node *node = floor(root, key);
return &(node->key);
}
int *BST::ceil(int key) {
if (count == 0 || key > maxinum()) {
return nullptr;
}
Node *node = ceil(root, key);
return &(node->key);
}
Node *BST::floor(Node *p, int key) {
if (p == nullptr) {
// attention 這兒返回空的含義
return nullptr;
}
// 如果p的key值和要尋找的key值相等
// 則p本身就是key的floor節點
if (p->key == key) {
return p;
}
// 如果p的key值比要尋找的key值大
// 則要尋找的key的floor節點一定在p的左子樹中
if (p->key > key) {
return floor(p->left, key);
}
// 如果p->key < key
// 則p有可能是key的floor節點, 也有可能不是(存在比p->key大但是小於key的其餘節點)
// 需要嘗試向p的右子樹尋找一下
Node *res = floor(p->right, key);
if (res != nullptr) {
return res;
}
return p;
}
Node *BST::ceil(Node *p, int key) {
if (p == nullptr) {
// attention 這兒返回空的含義
return nullptr;
}
// 如果p的key值和要尋找的key值相等
// 則p本身就是key的ceil節點
if (p->key == key) {
return p;
}
// 如果p的key值比要尋找的key值小
// 則要尋找的key的ceil節點一定在p的右子樹中
if (p->key < key) {
return ceil(p->right, key);
}
// 如果p->key > key
// 則p有可能是key的ceil節點, 也有可能不是(存在比p->key小但是大於key的其餘節點)
// 需要嘗試向p的左子樹尋找一下
Node *res = ceil(p->left, key);
if (res != nullptr) {
return res;
}
return p;
}
測試
// 二叉搜尋樹測試
void BSTTest() {
BST bstree;
// 插入
bstree.insert(5, 50);
bstree.insert(4, 40);
bstree.insert(9, 90);
bstree.insert(1, 10);
bstree.insert(7, 70);
bstree.insert(3, 30);
bstree.insert(6, 60);
bstree.insert(8, 80);
bstree.insert(11, 110);
bstree.insert(10, 100);
// 深度遍歷遍歷
bstree.preOrder();
std::cout << std::endl;
bstree.inOrder();
std::cout << std::endl;
bstree.postOrder();
std::cout << std::endl;
// 廣度遍歷
bstree.levelOrder();
std::cout << std::endl;
// 搜尋
auto sv = bstree.search(10);
bool cv = bstree.contain(10);
sv = bstree.search(11);
cv = bstree.contain(11);
sv = bstree.search(8);
cv = bstree.contain(8);
sv = bstree.search(13);
cv = bstree.contain(13);
// 最大最小值
int minnum = bstree.mininum();
int maxnum = bstree.maxinum();
// bstree.removeMin();
// bstree.levelOrder();
// std::cout << std::endl;
// bstree.removeMax();
// bstree.levelOrder();
// std::cout << std::endl;
// 刪除任意節點
// bstree.removeNode(8);
// bstree.levelOrder();
// std::cout << std::endl;
// bstree.removeNode(1);
// bstree.levelOrder();
// std::cout << std::endl;
// bstree.removeNode(4);
// bstree.levelOrder();
// std::cout << std::endl;
// bstree.removeNode(8);
// bstree.levelOrder();
// std::cout << std::endl;
// bstree.removeNode(9);
// bstree.levelOrder();
// std::cout << std::endl;
// floor/ceil
auto floorv = bstree.floor(4);
floorv = bstree.floor(2);
floorv = bstree.floor(0);
floorv = bstree.floor(3);
auto ceilv = bstree.ceil(5);
ceilv = bstree.ceil(12);
ceilv = bstree.ceil(2);
ceilv = bstree.ceil(3);
ceilv = bstree.ceil(8);
return;
}
參考:
https://blog.csdn.net/weixin_42983849/article/details/105622493