原理
左节点比根节点小,右结点比根结点大
API设计
结点类:
Node<Value>
public Node* left
public Node* right
public int key
public Value value
二叉查找树:
BinaryTree<Value>
private Node* root //根节点
private int N //元素个数
public void put(Key key,Value value) //向树插入键值对
private Node* put(Node* x,Key key,Value val) //给指定树x上添加一个键值对,并返回添加后的新树
public Value get(Key key) //找寻key结点的值
private Value get(Node x,Key key) //从指定的树中找出key对应的值
public void deleteNode(Key key) //删除key结点
private Node* deleteNode(Node* x,Key key) //从指定的树中删除key结点
public int size()
代码实现
#include <iostream>
#include <cstdlib>
#include <string>
using namespace std;
template <typename Value>
class Node
{
public:
int key;
Value value;
Node* left;
Node* right;
Node() = default;
Node(int key,Value value, Node* left, Node* right){
this->key = key;
this->value = value;
this->left = left;
this->right = right;
}
};
template <typename Value>
class binary_tree
{
public:
binary_tree(){
num = 0;
root = nullptr;
}
~binary_tree(){}
int size(){
return num;
}
//向树中添加元素key-value
void put(int key, Value value){
root = put(root, key, value);
}
//向指定的树中添加元素key-value
Node<Value>* put(Node<Value>* x, int key,Value value){
//如果是空树
if(x == nullptr){
num++;
return new Node<Value>(key, value, nullptr, nullptr);
}
//不是空树
//待插入结点的key与当前节点的key值作比较
//待插入结点的key大于当前结点的key,将待插入结点插入到当前结点的右子树
if(key > x->key){
x->right = put(x->right, key, value);
}
//待插入结点的key小于当前结点的key,将待插入结点插入到当前结点的左子树
else if(key < x->key){
x->left = put(x->left, key, value);
}
//待插入结点的key等于当前结点的key,直接改变当前结点的value即可
else{
x->value = value;
}
return x;
}
//查询树中指定key对应的value
Value get(int key){
return get(root, key);
}
//从指定的树x中,查找key对应的值
Value get(Node<Value>* x, int key){
if(x == nullptr){
return nullptr;
}
//待查找的key大于当前结点的key,查找当前结点的右子树
if(key > x->key){
return get(x->right, key);
}
//待查找的key小于当前结点的key,查找当前结点的左子树
else if(key < x->key){
return get(x->left, key);
}
//待插入结点的key等于当前结点的key,返回当前结点的value
else{
return x->value;
}
}
//删除树中key对应的value
void deleteNode(int key){
root = deleteNode(root, key);
}
//删除指定树x中的key对应的value,并返回删除后的新树
Node<Value>* deleteNode(Node<Value>* x, int key){
if(x == nullptr){
return nullptr;
}
//待删除结点的key大于当前结点的key,查找当前结点的右子树
if(key > x->key){
x->right = deleteNode(x->right, key);
}
//待插入结点的key小于当前结点的key,查找当前结点的左子树
else if(key < x->key){
x->left = deleteNode(x->left, key);
}
//待插入结点的key等于当前结点的key,删除当前结点
else{
Node<Value>* newNode;
//如果当前结点的左子树为空,直接返回当前节点的右子树
if(x->left == nullptr){
newNode = x->right;
delete x;
num--;
return newNode;
}
//如果当前结点的右子树为空,直接返回当前节点的左子树
else if(x->right == nullptr){
newNode = x->left;
delete x;
num--;
return newNode;
}
else{
//找到右子树中最小的结点重建子树:最小结点即为右子树的最左结点
Node<Value>* minNode = x->right;
//新建n结点用于保存最左结点的父节点
Node<Value>* n;
//找到最左节点
while(minNode->left != nullptr){
n = minNode;
minNode = minNode->left;
}
//删除最左节点
n->left = nullptr;
//重建子树
minNode->right = x->right;
minNode->left = x->right;
delete x;
num--;
return minNode;
}
}
}
private:
Node<Value>* root;
int num;
};
//测试代码
int main()
{
binary_tree<string> bt;
bt.put(4, "二哈");
bt.put(1, "张三");
bt.put(3, "李四");
bt.put(5, "王五");
cout << bt.size()<<endl;
bt.put(1,"老三");
cout << bt.get(1) << endl;
cout << bt.size() << endl;
cout << bt.get(3) << endl;
cout << bt.get(4) << endl;
cout << bt.get(5) << endl;
bt.deleteNode(1);
bt.deleteNode(3);
cout << bt.size() << endl;
return 0;
}