二分搜索树最难的操作是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; }