二叉搜索树
二叉搜索树是一以二叉树来组织的,可以用链表的数据结构来表示,每一个结点就是一个对象,包括以下的结构:
BSTNode<K, V>* _pLeft;
BSTNode<K, V>* _pRight;
BSTNode<K, V>* _parent;
K _key;
V _value;
二叉搜索树或者是一棵空树,或者是具有以下性质的二叉树:
1、若它的左子树不为空,则左子树上所有结点的值都小于根结点的值
2、若它的右子树不为空,则右子树上所有结点的值都大于根结点的值
3、它的左右子树也分别为二叉搜索树
搜索
基本思想:
如果根结点不为空,我们需要查找的key等于根结点的key,返回根节点的指针;如果查找key小于根结点的key,在其左子树中查找;如果查找key大于根结点的key,在其右子树中查找。否则,返回false
代码实现:
PNode Find(const K& key)
{
PNode pRoot = _pRoot;
if (pRoot)
{
if (key == pRoot->_key)
return pRoot;
else if (key < pRoot->_key)
{
pRoot = pRoot->_pLeft;
}
else
{
pRoot = pRoot->_pRight;
}
}
return false;
}
插入
基本思想:
空树—->new Node—>return true
非空—->搜索需要插入的位置—->插入
代码实现:
//插入
bool Insert(const K& key, const V& va
{
PNode pRoot = _pRoot;
PNode newNode = new Node(key, val);
//树为空
if (pRoot == NULL)
{
_pRoot = newNode;
return true;
}
//树非空
PNode pParent = NULL;
//1.找到待插入的结点的位置
while (pRoot)
{
if (key == pRoot->_key)
return false;
else if (key < pRoot->_key)
{
pParent = pRoot;
pRoot = pRoot->_pLeft;
}
else
{
pParent = pRoot;
pRoot = pRoot->_pRight;
}
}
//2.插入新结点
if (key < pParent->_key)
pParent->_pLeft = newNode;
if (key > pParent->_key)
pParent->_pRight = newNode;
return true;
}
删除
基本思想:
①空树—>直接返回
②非空—>找待删除的结点–>
不在树中–>直接返回
在树中
a.没有左右孩子(和b或c合并)
b.只有左孩子
(1)根节点
(2)非根节点(两种情况,当前结点为上一结点的左孩子、右孩子 c.只有右孩子 d.左右孩子均存在
代码实现:
//删除
bool Delete(const K& key)
{
PNode pDel = _pRoot;
PNode pParent = NULL;
//树为空
if (_pRoot == NULL)
return false;
//树非空
//1.找到待删除的结点的位置
while (pDel)
{
if (pDel->_pLeft)
{
pParent = pDel;
pDel = pDel->_pLeft;
}
else
{
pParent = pDel;
pDel = pDel->_pRight;
}
}
if (pDel)
{
//只有左孩子
if (pDel->_pRight == NULL)
{
if (pDel == _pRoot)//删除结点为根结
_pRoot = pDel->_pLeft;
else
pParent->_pLeft= pDel;
delete pDel;
}
//只有右孩子
else if (pDel->_pLeft == NULL)
{
if (pDel == _pRoot)//为根结点
_pRoot = pDel->_pRight;
else
pParent->_pRight = pDel;
delete pDel;
}
//左右孩子都存在
else
{
//找中序遍历的后一个结点作为替代结点
PNode pRL = pDel->_pRight;
while (pRL && pRL->_pLeft)
{
pRL = pRL->_pLeft;
}
if (pRL->_pRight)//pRL有右子树
pParent->_pLeft = pRL;
else
pParent->_pLeft = NULL;
pParent->_pRight = pDel->_pRight;
PNode ppParent = pParent->_parent;
if (pDel == _pRoot)
_pRoot->_key = pRL->_key;
else
pParent->_key = pRL->_key;
}
}
return false;
}
全部代码:
#include <iostream>
using namespace std;
template <class K,class V>
struct BSTNode
{
BSTNode(const K& key,const V& value)
: _pLeft(NULL)
, _pRight(NULL)
, _parent(NULL)
, _key(key)
, _value(value)
{}
BSTNode<K, V>* _pLeft;
BSTNode<K, V>* _pRight;
BSTNode<K, V>* _parent;
K _key;
V _value;
};
template <class K,class V>
class BSTree
{
public:
typedef BSTNode<K, V> Node;
typedef Node* PNode;
BSTree()
:_pRoot(NULL)
{}
循环实现//
//搜索
PNode Find(const K& key)
{
PNode pRoot = _pRoot;
if (pRoot)
{
if (key == pRoot->_key)
return pRoot;
else if (key < pRoot->_key)
{
pRoot = pRoot->_pLeft;
}
else
{
pRoot = pRoot->_pRight;
}
}
return false;
}
//插入
bool Insert(const K& key, const V& value)
{
PNode pRoot = _pRoot;
PNode newNode = new Node(key, value);
//树为空
if (pRoot == NULL)
{
_pRoot = newNode;
return true;
}
//树非空
PNode pParent = NULL;
//1.找到待插入的结点的位置
while (pRoot)
{
if (key == pRoot->_key)
return false;
else if (key < pRoot->_key)
{
pParent = pRoot;
pRoot = pRoot->_pLeft;
}
else
{
pParent = pRoot;
pRoot = pRoot->_pRight;
}
}
//2.插入
if (key < pParent->_key)
pParent->_pLeft = newNode;
if (key > pParent->_key)
pParent->_pRight = newNode;
return true;
}
//删除
bool Delete(const K& key)
{
PNode pDel = _pRoot;
PNode pParent = NULL;
//树为空
if (_pRoot == NULL)
return false;
//树非空
//1.找到待删除的结点的位置
while (pDel)
{
if (pDel->_pLeft)
{
pParent = pDel;
pDel = pDel->_pLeft;
}
else
{
pParent = pDel;
pDel = pDel->_pRight;
}
}
if (pDel)
{
//只有左孩子
if (pDel->_pRight == NULL)
{
if (pDel == _pRoot)//删除结点为根结点
_pRoot = pDel->_pLeft;
else
pParent->_pLeft= pDel;
delete pDel;
}
//只有右孩子
else if (pDel->_pLeft == NULL)
{
if (pDel == _pRoot)//为根结点
_pRoot = pDel->_pRight;
else
pParent->_pRight = pDel;
delete pDel;
}
//左右孩子都存在
else
{
//找中序遍历的后一个结点作为替代结点(右子树的最左边的结点)
PNode pRL = pDel->_pRight;
while (pRL && pRL->_pLeft)
{
pRL = pRL->_pLeft;
}
if (pRL->_pRight)//pRL有右子树
pParent->_pLeft = pRL;
else
pParent->_pLeft = NULL;
pParent->_pRight = pDel->_pRight;
PNode ppParent = pParent->_parent;
if (pDel == _pRoot)
_pRoot->_key = pRL->_key;
else
pParent->_key = pRL->_key;
}
}
return false;
}
PNode Root()
{
return _pRoot;
}
private:
PNode _pRoot;
};
void BinSearchTest()
{
BSTree<int, int> t;
BSTree<int, int>* pRoot = NULL;
t.Insert(1, 0);
t.Insert(3, 1);
t.Insert(2, 2);
t.Insert(5, 3);
t.Delete(5);
}