提示:文章写完后,目录可以自动生成,如何生成可参考右边的帮助文档
搜索树
搜索树适用于字典描述,与跳表和散列相比,二叉搜索树和平衡搜索树使用更加灵活,在最坏的情况下性能有保证。
二叉搜索树:
是一棵二叉树,可能为空,非空的二叉搜索树满足以下特征:
1.每个元素都有唯一的关键字
2.根节点的左子树中,元素的关键字都小于根节点的关键字
3.根节点的右子树中,元素的关键字都大于根节点的关键字
4.根节点左右子树也都是二叉搜索树
a就不是二叉搜索树(不满足4),bc是二叉搜索树。
注: 有重复值的二叉搜索树, 小于–>小于等于
索引二叉搜索树:
源于普通的二叉搜索树,只是在每个节点中添加一个leftSize域,表示该节点的左子树的元素个数:
二叉搜索树的操作:
1. 搜索:
假设需要查找的关键字为theKey,则先从根节点开始查找,如果为空,则树不包含任何元素;否则,将theKey和根节点的关键字进行比较,如果等于,则查找成功,如果theKey小于根节点的关键字,则查找左子树即可,否则,查找右子树。
2. 插入
假设要在二叉搜索树中插入一个元素,首先通过查找来确定,要插入的元素的关键字在树中是否存在,如果存在,则用插入元素的value覆盖掉原来的value,否则,将元素插入树中:
3. 删除
要考虑三种情况:
1.要删除的节点是树叶:
2.要删除的节点有一棵子树
3.要删除的节点有两棵子树
二叉搜索树的实现
// 定义二叉搜索树树
#ifndef BSTREE_H
#define BSTREE_H
#include <algorithm>
#include <iostream>
using namespace std;
// 定义二叉搜索树的节点
template<typename K=int, typename V=int> // key: value类型的节点
struct BSTreeNode
{
BSTreeNode* leftchild;
BSTreeNode* rightchild;
K key;
V value;
BSTreeNode(K& theKey, V& theValue)
{
key = theKey;
value = theValue;
leftchild = NULL;
rightchild = NULL;
}
};
template<typename K, typename V>
class BSTree
{
typedef BSTreeNode<K, V> BSTreeNode;
private:
BSTreeNode* root; // 二叉搜索树的根节点
int treeSize;
void destory(BSTreeNode* mroot); // 删除二叉树的所有节点 // 析构函数
BSTreeNode* find(K theKey, BSTreeNode* mroot);
void insert(K theKey, V theValue, BSTreeNode* mroot);
void remove(K theKey, BSTreeNode* mroot); // 删除特定的节点
void out_put(BSTree* mroot);
public:
BSTree();
~BSTree();
// void destory();
// 查找二叉树的节点
BSTreeNode* find(K theKey); // 参数:键值
void insert(K theKey, V theValue);
void remove(K theKey);
void out_put();
};
template<typename K, typename V>
void BSTree<K, V>::destory(BSTreeNode* mroot)
{
// 删除所有节点 递归调用
if(mroot!=NULL)
{
destory(mroot->leftchild);
destory(mroot->rightchild);
delete mroot;
}
}
template<typename K, typename V>
BSTree<K, V>::BSTree()
{
treeSize = 0;
root = NULL;
}
template<typename K, typename V>
BSTree<K, V>::~BSTree()
{
// 删除二叉树的节点
destory(root);
}
template<typename K, typename V>
BSTreeNode* BSTree<K, V>::find(K theKey)
{
// 二叉搜索树的查找函数
// 根据关键字查找:
return find(theKey, root);
}
template<typename K, typename V>
BSTreeNode* BSTree<K, V>::find(K theKey, BSTreeNode* mroot)
{
if(mroot != NULL)
{
if(mroot->key==theKey)
{
return mroot;
}
else if(mroot->key>theKey) // 搜索左子树
{
return find(theKey, mroot->leftchild); // 递归的方法
}
else // 搜索右子树
{
return find(theKey, mroot->rightchild);
}
}
return NULL; // 没有找到
}
template<typename K, typename V>
void BSTree<K, V>::insert(K theKey, V theValue, BSTreeNode* mroot)
{
// NULL
if(mroot==NULL)
{
mroot = new BSTreeNode(theKey, theValue);
return; // 递归结束
}
if(mroot->key==theKey) // 关键字已经存在
{
mroot->value = theValue;
return; // 结束递归
}
else if(theKey < mroot->key) // 插入左子树
{
insert(theKey, theValue, mroot->leftchild);
}
else // 插入右子树
{
insert(theKey, theValue, mroot->rightchild);
}
}
template<typename K, typename V>
void BSTree<K, V>::insert(K theKey, V theValue)
{
insert(theKey, theValue, root);
}
template<typename K, typename V>
void BSTree<K, V>::remove(K theKey, BSTreeNode* mroot)
{
/*
if(mroot==NULL) // 结束的条件
{
cout << "No such node" << endl;
return;
}
*/
// 只有一个节点
if(mroot->leftchild==NULL && mroot->rightchild==NULL) // 最底层的节点
{
if(root->key==theKey) // 是要查找的节点
{
delete mroot;
mroot = NULL;
return;
}
}
if(theKey<mroot->key) // 搜索左子树
{
remove(theKey, mroot->leftchild);
}
else if(theKey>mroot->key)
{
remove(theKey, mroot->rightchild); // 搜索右子树
}
else // 相等。且不是最底层的节点
{
BSTreeNode* del = NULL; // 临时的指针
if(mroot->leftchild==NULL) // 只有右孩子
{
del = mroot;
mroot = mroot->rightchild; // 取右孩子
delete del;
del = NULL;
return;
}
else if(mroot->rightchild==NULL) // 只有左孩子
{
del = mroot;
mroot = mroot->leftchild;
delete del;
del = NULL;
return;
}
else // 要删除的节点有左右子树
{
BSTreeNode* rightFirst = mroot->rightchild; // 获取要删除的节点的右孩子
while(rightFirst->leftchild!=NULL)
{
rightFirst = rightFirst->leftchild;
}
// 交换
// 将要删除的节点交换到最底层
swap(mroot->key, rightFirst->key);
swap(mroot->value, rightFirst->value);
remove(theKey, mroot->rightchild); // 接着删除
return; // ?
}
}
}
template<typename K, typename V>
void BSTree<K, V>::remove(K theKey)
{
remove(theKey, root);
}
template<typename K, typename V>
void BSTree<K, V>::out_put(BSTreeNode* mroot)
{
if(mroot==NULL)
{
return;
}
out_put(mroot->leftchild);
cout << "key: " << mroot->key << " value: " << mroot->value << " ";
out_put(mroot->rightchild);
}
template<typename K, typename V>
void BSTree<K, V>::out_put()
{
out_put(root);
}
#endif