【C++】实现的二叉搜索树BST
2016-07-07 22:30
567 查看
概念:
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树),二叉搜索树是一种特殊的二叉树二叉搜索树的性质:
1. 每个节点都有一个作为搜索依据的关键码(key),所有节点的关键码互不相同。2. 左子树上所有节点的关键码(key)都小于根节点的关键码(key)。
3. 右子树上所有节点的关键码(key)都大于根节点的关键码(key)。
4. 左右子树都是二叉搜索树。
根据二叉搜索树的性质知:对二叉搜索树进行中序遍历得到的结点序列必然是一个有序序列。
接下来用C++代码实现搜索二叉树,若有错误或不足之处,还望各位大神指点。。。
代码:(代码中间包含了对基本功能(插入,删除,查找)的递归和非递归的实现)
[cpp] viewplain copy
<span style="font-size:18px;">include <iostream>
#include <string>
using namespace std;
template<class K,class V>
struct BSTreeNode
{
K _data; //值
V _freq; //出现的频率
BSTreeNode<K, V>* _left; //指向左子树的指针
BSTreeNode<K, V>* _right; //指向右子树的指针
BSTreeNode(const K& data, const V& freq)//初始化
:_data(data)
, _freq(freq)
, _left(NULL)
, _right(NULL)
{}
};
template<class K, class V>
struct BSTree
{
typedef BSTreeNode<K, V> Node;
public:
BSTree()//初始化
:_root(NULL)
{}
//插入
bool Insert(const K& data, const V& freq)
{
if (_root == NULL)//如果节点为空,就在此节点处加入data数据
{
_root = new Node(data, freq);
return true;
}
Node* parent = NULL;
Node* cur = _root;
while (cur)//搜索data应该插入的节点:parent节点后
{
if (data > cur->_data)//如果data大于节点的值,就继续在节点的右子树中插入data
{
parent = cur;
cur = cur->_right;
}
else if (data < cur->_data)//如果data小于节点的值,就继续在节点的左子树中插入data
{
parent = cur;
cur = cur->_left;
}
else
{
cur->_freq++;
return true;
}
}
//在parent节点后插入data
if (data > parent->_data)
{
parent->_right = new Node(data, freq);
}
else
{
parent->_left = new Node(data, freq);
}
return true;
}
Node* Find(const K& data)//查找
{
Node* cur = _root;
while (cur)
{
if (data >cur->_data)//若data大于当前节点,则在当前节点的右子树中查找
{
cur = cur->_right;
}
else if (data < cur->_data)//若data小于当前节点,则在当前节点的左子树中查找
{
cur = cur->_left;
}
else
{
return cur;
}
}
return NULL;
}
bool Remove(const K& data)//删除
{
Node* parent = NULL;
Node* cur = _root;
while (cur)//寻找data节点cur
{
if (data > cur->_data)
{
parent = cur;
cur = cur->_right;
}
else if (data < cur->_data)
{
parent = cur;
cur = cur->_left;
}
else//要么cur==NULL退出了循环,要么data==cur->_databreak
{
break;
}
}
if (cur == NULL)
{
return false;
}
//1.左为空,或者右为空
//2.左右都不为空
if (cur->_left == NULL)
{//cur的左为空
if (parent == NULL)//删除的是根节点
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
delete cur;
}
else if (cur->_right == NULL)
{//cur的右为空
if (parent == NULL)
{
_root = cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
delete cur;
}
else
{//左不为空,右也不为空
parent = cur;
Node *subLeft = cur->_right;//subarea node 子区节点
while (subLeft->_left)
{//遍历删除节点的左子树??
parent = subLeft;
subLeft = subLeft->_left;
}
cur->_data = subLeft->_data;
cur->_freq = subLeft->_freq;
if (parent->_left == subLeft)
{
parent->_left = subLeft->_right;
}
else
{
parent->_right = subLeft->_right;
}
delete subLeft;
}
return true;
}
//以下是递归方式
bool InsertR(const K& data, const V& freq)
{
return _InsertR(_root, data, freq);
}
bool _InsertR(Node*& root, const K& data, const V& freq)
{
if (root == NULL)
{
root = new Node(key, freq);
return true;
}
if (data > root->_data)
{
return _InsertR(root->_right, key, freq);
}
else if (data < root->_data)
{
return _InsertR(root->_left, key, freq);
}
else
{
return false;
}
}
Node* FindR(const K& data)
{
return _FindR(_root, data);
}
Node* _FindR(Node*& root, const K& data)
{
if (root == NULL)
{
return NULL;
}
if (data > root->_data)
{
return _FindR(root->_right, key);
}
else if (data < root->_data)
{
return _FindR(root->_left, key);
}
else
{
return root;
}
}
bool RemoveR(const K& data)
{
return _RemoveR(_root, data);
}
bool _RemoveR(Node*& root, const K& data)
{
if (root == NULL)
{
return false;
}
if (data > root->_data)
{
return _RemoveR(root->_right, data);
}
else if (data < root->_data)
{
return _RemoveR(root->_left, data);
}
else
{
Node* del = root;
if (root->_left == NULL)
{
root = root->_right;
}
else if (root->_right == NULL)
{
root = root->_left;
}
else
{
Node* parent = root;
Node* subLeft = root->_right;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
root->_data = subLeft->_data;
root->_freq = subLeft->_freq;
del = subLeft;
if (parent->_left == subLeft)
{
parent->_left = subLeft->_right;
}
else
{
parent->_right = subLeft->_right;
}
}
delete del;
return true;
}
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
void _InOrder(Node* root)
{
if (root == NULL)
return;
_InOrder(root->_left);
cout << root->_data << " ";
_InOrder(root->_right);
}
protected:
Node* _root;
};</span>
在删除算法过程中要注意细节情况
1.删除根节点
2.删除叶子节点
3.删除带有子树的节点
算法分析:
它和二分查找一样,插入和查找的时间复杂度均为lgN,但是在最坏的情况下仍然会有N的时间复杂度。原因在于插入和删除元素的时候,树没有保持平衡。我们追求的是在最坏的情况下仍然有较好的时间复杂度,这就是后面要讲的平衡查找树的内容了。下文首先讲解平衡查找树的最简单的一种:2-3查找树。BST与二分查找一样,插入与查找的时间复杂度均为lgN,但是BST最坏情况是插入一个本身的有序的数列,这样在构建BST时会退化成类似于数组结构
即:
有一篇BST分析的很到位,链接是:
http://www.cnblogs.com/yangecnu/p/Introduce-Binary-Search-Tree.html
所以也就衍生出AVL树即平衡二叉查找树
相关文章推荐
- 使用C++实现JNI接口需要注意的事项
- 关于指针的一些事情
- c++ primer 第五版 笔记前言
- share_ptr的几个注意点
- Lua中调用C++函数示例
- Lua教程(一):在C++中嵌入Lua脚本
- Lua教程(二):C++和Lua相互传递数据示例
- C++联合体转换成C#结构的实现方法
- C++高级程序员成长之路
- C++编写简单的打靶游戏
- C++ 自定义控件的移植问题
- C++变位词问题分析
- C/C++数据对齐详细解析
- C++基于栈实现铁轨问题
- C++中引用的使用总结
- 使用Lua来扩展C++程序的方法
- C++中调用Lua函数实例
- Lua和C++的通信流程代码实例
- C++的template模板中class与typename关键字的区别分析
- C与C++之间相互调用实例方法讲解