一.搜索二叉树
1.1搜索二叉树的概念
搜索二叉树又叫排序二叉树,搜索二叉树可以为空,如果不为空应满足以下条件。
若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
它的左右子树也分别为二叉搜索树
1.2 二叉搜索树操作
1.2.1搜索二叉树的查找
a、从根开始比较,查找,比根大则往右边走查找,比根小则往左边走查找。
b、最多查找高度次,走到到空,还没找到,这个值不存在。
1.2.2搜索二叉树的插入
a、从根开始如果根为空,就新建节点赋值给根的指针
b、根不为空就按照搜索二叉树的性质找到插入的位置,插入新的节点
1.2.3搜索二叉树的删除
首先查找元素是否在二叉搜索树中,如果不存在,则返回, 否则要删除的结点可能分下面四种情 况:
a. 要删除的结点无孩子结点
b. 要删除的结点只有左孩子结点
c. 要删除的结点只有右孩子结点
d. 要删除的结点有左、右孩子结点
看起来有待删除节点有4中情况,实际情况a可以与情况b或者c合并起来,因此真正的删除过程如下:
情况b:删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点--直接删除
情况c:删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点--直接删除
情况d:在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点 中,再来处理该结点的删除问题--替换法删除
二.搜索二叉树的实现
template<class K>
struct Node
{
struct Node<K>* left;
struct Node<K>* right;
K _key;
Node(const K& key)
:left(nullptr)
,right(nullptr)
,_key(key)
{}
};
template<class K>
class BST
{
typedef struct Node<K> node;
public:
bool Insert(const K& key)
{
node* parent = nullptr;
node* cur = _root;
if (nullptr == _root)
{
_root = new node(key);
return true;
}
while (cur)
{
parent = cur;
if (cur->_key > key)
{
cur = cur->left;
}
else if (cur->_key < key)
{
cur = cur->right;
}
else
{
return false;
}
}
node* tmp = new node(key);
if (parent->_key > key)
{
parent->left = tmp;
}
else
{
parent->right = tmp;
}
return true;
}
bool Find(const K& key)
{
node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
cur = cur->left;
}
else if (cur->_key < key)
{
cur = cur->right;
}
else
{
return true;
}
}
return false;
}
bool Erase(const K& key)
{
node* parent = nullptr;
node* cur = _root;
while (cur)
{
if (cur->_key > key)
{
parent = cur;
cur = cur->left;
}
else if (cur->_key < key)
{
parent = cur;
cur = cur->right;
}
else
{
if (nullptr == cur->left)
{
if (cur == _root)
{
_root = cur->right;
}
else
{
if (parent->left == cur)
{
parent->left = cur->right;
}
else
{
parent->right = cur->right;
}
}
}
else if (nullptr == cur->right)
{
if (cur == _root)
{
_root = cur->left;
}
else
{
if (parent->left == cur)
{
parent->left = cur->left;
}
else
{
parent->right = cur->left;
}
}
}
else
{
node* parent = cur;
node* sub_right_min = cur->right;
while (sub_right_min->left)
{
parent = sub_right_min;
sub_right_min = sub_right_min->left;
}
swap(sub_right_min->_key, cur->_key);
if (parent->left == sub_right_min)
{
parent->left = sub_right_min->right;
}
else
{
parent->right = sub_right_min->right;
}
}
return true;
}
}
return false;
}
void InOrder()
{
_InOrder(_root);
cout << endl;
}
bool FindR(const K& key)
{
return _FindR(_root,key);
}
bool EraseR(const K& key)
{
return _EraseR(_root,key);
}
bool InsertR(const K& key)
{
return _InsertR(_root, key);
}
private:
bool _InsertR(node*& root,const K& key)
{
if (root == nullptr)
{
root = new node(key);
return true;
}
else
{
if (root->_key > key)
{
return _InsertR(root->left, key);
}
else if (root->_key < key)
{
return _InsertR(root->right,key);
}
else
{
return false;
}
}
}
bool _EraseR(node*& root, const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key > key)
{
return _EraseR(root->left,key);
}
else if (root->_key < key)
{
return _EraseR(root->right,key);
}
else
{
if (root->left == nullptr)
{
node* del = root;
root = root->right;
delete del;
}
else if (root->right == nullptr)
{
node* del = root;
root = root->left;
delete del;
}
else
{
node* sub_right_min = root->right;
while (sub_right_min->left)
{
sub_right_min = sub_right_min->left;
}
swap(root->_key, sub_right_min->_key);
return _EraseR(root->right, key);
}
}
}
bool _FindR(node* root,const K& key)
{
if (root == nullptr)
{
return false;
}
if (root->_key > key)
{
return _FindR(root->left);
}
else if(root->_key < key)
{
return _FindR(root->right);
}
else
{
return true;
}
}
void _InOrder(node* root)
{
if (nullptr == root)
{
return;
}
_InOrder(root->left);
cout<<root->_key<<" ";
_InOrder(root->right);
}
private:
node* _root = nullptr;
};
三.搜索二叉树的性能分析
搜索二叉树用的最多的应该就是查找了,所以可以用查找来代表搜索二叉树的性能
最优情况,搜索二叉树是完全二叉数:时间复杂度就是log₂N。
最坏情况,搜索二叉树为单支树:时间复杂度是N²