二叉搜索树注重增删查改,现在针对key/value形式进行研究。
现在对其进行实现,分别有插入,查找,删除,分别对这几个功能用递归和非递归实现。
其中删除操作比较特别,分为
3种,分别是删除叶子节点,删除左为空或右为空的节点,
第三种是删除左右子树都不为空的节点。最后一种删除最麻烦,它分为三个步骤,分别是找出右树的最左节点,然后和要删除的节点进行key/value的互换,然后再删除它最左节点。
代码实现:
template<class K,class V>
struct BinarySearchTreeNode //key/value形式
{
BinarySearchTreeNode( const K & key, const V& value)
:_key( key)
, _value( value)
, _left( NULL)
, _right( NULL)
{}
K _key;
V _value;
BinarySearchTreeNode<K , V>* _left;
BinarySearchTreeNode<K , V>* _right;
};
template<class K, class V>
class BinarySearchTree
{
typedef BinarySearchTreeNode <K, V> Node;
public:
BinarySearchTree()
:_root( NULL)
{}
bool Insert(const K& key,const V& value)//插入(非递归)
{
if (_root == NULL )//开始无节点
{
_root = new Node (key, value);
return true ;
}
Node* parent = NULL ;
Node* cur = _root;
while (cur)
{
if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else if (key>cur->_key)
{
parent = cur;
cur = cur->_right;
}
else
return false ;
}
if (parent->_key > key )
parent->_left = new Node (key, value);
else
parent->_right = new Node (key, value);
return true ;
}
bool InsertR(const K& key,const V& value)//插入(递归)
{
return _InsertR(_root, key , value);
}
Node* Find(const K& key)//查找(非递归)
{
if (_root == NULL )
return NULL ;
Node* cur = _root;
while (cur)
{
if (cur->_key == key )
return cur;
else if (key < cur->_key)
cur = cur->_left;
else
cur = cur->_right;
}
return NULL ;
}
Node* FindR(const V& key)//插入(递归)
{
return _FindR(_root, key );
}
bool Remove(const K& key)//删除节点(非递归)
{
if (_root == NULL )
return false ;
Node* cur = _root;
Node* parent=NULL ;
while (cur)
{
if (key < cur->_key)
{
parent = cur;
cur = cur->_left;
}
else if (key>cur->_key)
{
parent = cur;
cur = cur->_right;
}
else//找到节点
{
if (cur->_left == NULL &&cur->_right == NULL)//叶子节点
{
Node* del = cur;
delete del;
del = NULL;
return true ;
}
else if (cur->_left == NULL||cur->_right == NULL)//右树或左树为空
{
Node* del = cur;
if (parent->_right==cur)
{
if (cur->_right == NULL )
{
parent->_right = cur->_left;
delete del;
del = NULL;
return true ;
}
else if (cur->_left == NULL)
{
parent->_right = cur->_right;
delete del;
del = NULL;
return true ;
}
}
else if (parent->_left==cur)
{
Node* del = cur;
if (cur->_left == NULL )
{
parent->_left = cur->_right;
delete del;
del = NULL;
return true ;
}
else if (cur->_right == NULL)
{
parent->_left = cur->_left;
delete del;
del = NULL;
return true ;
}
}
}
if (cur->_left != NULL &&cur->_right != NULL)//左树和右树都不为空
{
Node* parent = cur;
Node* FirstLeft = cur->_right;
while (FirstLeft->_left)//找右树的最左节点
{
parent = FirstLeft;
FirstLeft = FirstLeft->_left;
}
swap(cur->_key, FirstLeft->_key);//交换
swap(cur->_value, FirstLeft->_value);
Node* del = FirstLeft;
if (parent->_left==FirstLeft)
parent->_left = FirstLeft->_right;
else
parent->_right = FirstLeft->_right;
delete del;
del = NULL;
return true ;
}
}
}
return false ;//未找到要删除的节点
}
bool RemoveR(const K& key)//删除(递归)
{
return _RemoveR(_root,key );
}
void InOrder()//中序遍历
{
_InOrder(_root);
cout << endl;
}
protected:
bool _RemoveR(Node *& root,const K& key )//删除会修改_root,用引用
{
if (root == NULL)
return false ;
if (key < root->_key)
_RemoveR( root->_left, key );
else if (key> root->_key)
_RemoveR( root->_right, key );
else//相等
{
if (root ->_right == NULL)//右子树为空
{
root = root ->_left;
delete root ;
root = NULL ;
return true ;
}
else if (root->_left == NULL)//左子树为空
{
root = root ->_right;
delete root ;
root = NULL ;
return true ;
}
else//左右子树都不为空
{
Node* FirstLeft = root ->_right;
Node* parent = root ;
while (FirstLeft->_left)//找最左节点
{
parent = FirstLeft;
FirstLeft = FirstLeft->_left;
}
swap( root->_key, FirstLeft->_key);//交换
swap( root->_value, FirstLeft->_value);
_RemoveR( root->_right, key );//继续递归右树的最左节点
}
}
}
bool _InsertR(Node *& root,const K& key,const V& value)//添加会修改_root,所以用引用
{
if (root == NULL)
{
root = new Node(key, value);
return true ;
}
if (key < root->_key)
_InsertR( root->_left, key , value);
else if (key> root->_key)
_InsertR( root->_right, key , value);
else//相等
return false ;
}
Node* _FindR(Node * root, const K& key)//查找
{
if (root == NULL)
return NULL ;
if (root ->_key == key)
return root ;
else if (key < root->_key)
_FindR( root->_left, key );
else
_FindR( root->_right, key );
}
void _InOrder(Node * root)//中序递归写法
{
if (root == NULL)
return;
_InOrder( root->_left);
cout << root->_value << " " ;
_InOrder( root->_right);
}
private:
Node* _root;
};
/*******************************************************************************************************************************************/
void test11()
{
BinarySearchTree<int , int> s1; //实现key/value形式的搜索树
int arr[10] = { 5, 3,1, 7 };
for (int i = 0; i < 4; i++)
{
s1.Insert(arr[i], i);
}
//s1.InOrder();
//cout << s1.Find(4)->_value << endl;
//cout << s1.Find(5)->_value << endl;
//cout << s1.Find(7)->_value << endl;
//s1.Remove(7);
//s1.Remove(3);
//s1.Remove(5);
//s1.InOrder();
cout << s1.FindR(1)->_value << endl;
}
void test2()
{
BinarySearchTree<int , int> s1; //实现key/value形式的搜索树
int arr[10] = { 5, 3, 1, 7 };
for (int i = 0; i < 4; i++)
{
s1.InsertR(arr[i], i);
}
//s1.InOrder();
s1.RemoveR(1);
s1.InOrder();
s1.RemoveR(5);
s1.InOrder();
}
二叉搜索树存在缺陷,就是左右分布十分不均匀,这样造成二叉搜索树的退化
例如:
需要解决这个问题就是平衡搜索树。