【数据结构】---模拟实现搜索二叉树
【数据结构】—模拟实现搜索二叉树引言:随着数据结构STL学习的不断深入,我们已经了解了序列式容器vector,list,string等,接下来进入到关联式容器中。两者都被用来存储数据,与序列式容器的线性结构不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树.
【数据结构】 模拟实现搜索二叉树
引言:随着数据结构STL学习的不断深入,我们已经了解了序列式容器vector,list,string等,接下来进入到关联式容器中。两者都被用来存储数据,与序列式容器的线性结构不同的是,其里面存储的是<key, value>结构的键值对,在数据检索时比序列式容器效率更高。根据应用场景的不同,STL总共实现了两种不同结构的管理式容器:树型结构与哈希结构。树型结构的关联式容器主要有四种:map、set、multimap、multiset。这四种容器的共同点是:使用平衡搜索树(即红黑树)作为其底层结果,容器中的元素是一个有序的序列。那么今天我们先来简单实现一下搜索二叉树吧。
二叉搜索树的概念:
二叉搜索树又称二叉排序树,它或者是一棵空树,或者是具有以下性质的二叉树:
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值 它的左右子树也分别为二叉搜索树
如图所示:
- 注:在整个实现过程中笔者发现,增添,查找,修改节点都是遍历整个树,直到找到key值返回true,都相对较为简单,比较令人头疼的就是删除操作,因为整个中序遍历后必须为有序,所以不能破坏整个树的大致结构,要让他时刻保持中序有序。
删除过程分以下三种情况:
1.左为空
2.有为空
3.左右都不为空
代码实现如下:
BinarySearch.h
#include<iostream>
using namespace std;
template<class k>
struct BSTreeNode
{
BSTreeNode<k>* _left;
BSTreeNode<k>* _right;
k _key;
BSTreeNode(const k& key)
:_key(key)
, _left(nullptr)
, _right(nullptr)
{}
};
template<class k>
class BSTree
{
typedef BSTreeNode<k> Node;
public:
BSTree()
:_root(nullptr)
{}
~BSTree()
{
delete _root;
_root=nullptr;
}
bool Insert(const k& key)
{
if (_root == nullptr)
{
_root = new Node(key);
return true;
}
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key>key)
{
parent = cur;
cur = cur->_left;
}
else
{
return false;
}
}
cur = new Node(key);
if (parent->_key < key)
parent->_right = cur;
else
parent->_left = cur;
return true;
}
Node* Find(const k& key)
{
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if (cur->_key>key)
{
cur = cur->_left;
}
else
{
return true;
}
}
return nullptr;
}
bool Erase(const k& key)
{
Node* parent = nullptr;
Node* cur = _root;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key>key)
{
parent = cur;
cur = cur->_left;
}
else//走到这表示找到了
{
//分为三种情况
//1.左为空
//2.右为空
//3.左右都不为空
Node* del = cur;
if (cur->_left == nullptr)
{
if (parent == nullptr)
{
_root=cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right == nullptr)
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
else
{
Node* lessparent = cur;
Node* rightLess = cur->_right;
while (rightLess->_left)
{
lessparent = rightLess;
rightLess = rightLess->_left;
}
cur->_key = rightLess->_key;
del = rightLess;
if (lessparent->_left == rightLess)
{
lessparent->_left = rightLess->_right;
}
else
{
lessparent->_right = rightLess->_right;
}
}
delete del;
return true;
}
}
return false;
}
void inOrder()
{
_inOrder(_root);
cout << endl;
}
void _inOrder(Node* root)
{
if (root == nullptr)
{
return;
}
_inOrder(root->_left);
cout << root->_key << " ";
_inOrder(root->_right);
}
//递归版本实现
bool InsertR(const k& key)
{
return _Insert(_root, key);
}
bool _Insert(Node* & root, const k& key)
{
if (root == nullptr)
root = new Node(key);
if (root->_key < key)
{
return _Insert(root = root->_right,key);
}
else if (root->_key>key)
{
return _Insert(root = root->_left, key);
}
else
{
return false;
}
}
Node* FindR(const k& key)
{
return _FindR(root->_key, key);
}
Node* _FindR(Node* root, const k& key)
{
if (root == nullptr)
return nullptr;
if (root->_key == key)
{
return root;
}
else if (root->_key < key)
{
return _FindR(root->_right, key);
}
else
{
return _FindR(root->_left, key);
}
}
bool EraseR( const k& key)
{
//Node* root=_root;
return _EraseR(root->_key, key);
}
bool _EraseR(Node* root, const k& key)
{
if (root == nullptr)
return false;
Node* cur = root;
Node* parent = cur;
if (cur->_key < key)
{
parent = cur;
return _EraseR(cur->_right,key);
}
else if (cur->_key>key)
{
parent = cur;
return _EraseR(cur->_left, key);
}
else
{
//分为三种情况
//1、左为空
//2、右为空
//3.左右都不为空
Node* del=cur;
if (cur->_left == nullptr)
{
if (parent == nullptr)
{
root = cur->_right;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
}
else if (cur->_right==nullptr)
{
if (parent == nullptr)
{
root = cur->_left;
}
else
{
if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
}
else
{
Node* Lessparent = nullptr;
Node* Lessright = cur->_right;
while (Lessright->_left)
{
Lessparent = Lessright;
Lessright = Lessright->_left;
}
cur->_key = Lessright->_key;
del = Lessright;
if (Lessparent->_left == Lessright)
{
Lessparent->_left = Lessright->_right;
}
else
{
Lessparent->_right = Lessright->_right;
}
}
delete del;
return true;
}
}
private:
Node* _root;
};
void TestBSTree()
{
int a[] = {5,3,4,1,7,8,2,6,0,9 };
BSTree<int> t;
for (auto e : a)
{
t.Insert(e);
}
t.inOrder();
t.EraseR(2);
t.EraseR(8);
t.EraseR(1);
t.EraseR(7);
t.EraseR(5);
t.inOrder();
}
Test.c
#define _CRT_SECURE_NO_WARNINGS 1
#include"BSTree.h"
int main()
{
TestBSTree();
system("pause");
return 0;
}
性能分析:
对有n个结点的二叉搜索树,若每个元素查找的概率相等,则二叉搜索树平均查找长度是结点在二叉搜索树的深度的函数,即结点越深,则比较次数越多。
最优情况下,二叉搜索树为完全二叉树,其平均比较次数为:log2^N
最差情况下,二叉搜索树退化为单支树,其平均比较次数为:2/N
更多推荐
所有评论(0)