什么是二叉搜索树
二叉搜索树是一种特殊的二叉树,它是被广泛运用的存储查找结构------完全平衡二叉树(AVLtree) 和红黑树的基础(RBtree)
二叉搜索树的规则:
- 二叉搜索树可以是一棵空树
- 如果其节点的左子树不空 则其左子树上的所有节点的值小于根节点的值
- 如果其节点的右子树不空 则其右子树上的所有节点的值小于根节点的值
- 每个节点的左右子树都是二叉搜索树
为什么要设计出这种规则的二叉搜索树呢? 其目的在于提高查询数据的效率 ,数据存储在树的结点中。
在满足此规则的二叉搜索树查找数据时 从根结点开始查找 如果要查找的值比当前节点小 则在当前节点的左子树中查找,
反之则在当前节点的右子树中查找
如果待查找的的值等于当前结点的值 则返回当前节点的值—查找找功。
如果查找到根节点时还未碰见与待查找值相同的节点 说明该书中没有这个数据 —–查找失败
二叉搜索树首先是一棵二叉树 他满足一棵普通二叉树的所有性质。
二叉搜索树的操作:
插入操作:
二叉搜索树一开始是一棵空树 插入第一个值时把第一个值构造结点作为根。
插入后续结点时,被插入的值和根节点的值和根节点的值作比较 ,大则和其左节点值相比较 小则和其右结点值相比较。再把 其左/右节点当作根节点比较 依次向下。 直到找到空节点 这时用要插入的值构造一个新节点用指针和其父节点连接起来。注意在查找可以插入的位置时有存储下来可能作为新插入节点父节点的节点以便插入。
如果找到了一个节点的值和被插入值相同 则树中已有该节点 插入失败 返回false;
代码实现:
bool Insert(const K& key, const V& value)
{
if (NULL == _pRoot){
_pRoot = new Node(key, value);
return true;
}
Node* pCur = _pRoot;
Node* pParent = pCur;
while (pCur){
if (key < pCur->_key)
{
pParent = pCur;
pCur = pCur->_pLeft;
}
else if (key > pCur->_key)
{
pParent = pCur;
pCur = pCur->_pRight;
}
else return false;
}
pCur = new Node(key, value);
if (key < pParent->_key)
nt->_key)
pParent->_pRight = pCur;
}
bool InsertR(const K& key,const V& v
{
_InsertR(_pRoot,key,value)
}
2.查找操作:
和插入操作非常相似按照插入操作相同的方式从根开始依次比较 和插入相反的是查找时遇到与查找值相;
的节点时返回该节点指针。
遇到NULL节点时说明树中没有该节点 返回fNULL;
代码:
Node* Find(const K& key)
{
Node* pCur = _pRoot;
while (pCur)
{
if (key < pCur->_key)
{
pCur = pCur->_pLeft;
}
else if (key > pCur->_key)
{
pCur = pCur->_pRight;
}
else return pCur;
}
return NULL;
}
3.删除操作:
删除操作相比前两个操作略有难度 难点在于删除一个节点之后整棵树仍需保持二叉搜索树的性质
删除操作中主要体现了替换法删除的思想
被删除的节点可以被分为以下几种情况:
1. 空树 ----return false;
2. 被删除的节点左节点为空 ----
1. 该节点为根节点
让树的根指向该节点的右子树
2. 该节点不是根节点
让该节点的父节点指向该节点的右子树
3. 被删除的节点右节点为空 ----
1. 该节点为根节点
让树的根指向该节点的左子树
2. 该节点不是根节点
让该节点的父节点指向该节点的左子树
4. 被删除节点的左右均不为空---------
找到该节点右子树的最左结点 把找到的这个节点的值赋给逻辑上要被删除的节点 并实际删除找到的这个 逻辑上要被删除右子树的最左节点。 此时根据二叉搜索树的性质该树依然合法。
其他情况均被包含在以上情况中
代码:
const K& GetMaxKey()const
{
Node* pCur = _pRoot;
while (pCur->_pRight)
pCur = pCur->_pRight;
return pCur;
}
bool Remove(const K& key)
{
Node* pParent = _pRoot;
Node* pCur = _pRoot;
while (pCur){
if (pCur->_key > key){
pParent = pCur;
pCur = pCur->_pLeft;
}
else if (pCur->_key < key){
pParent = pCur;
pCur = pCur->_pRight;
}
else{
break;
}
}
if (pCur)
{
if (pCur->_pLeft == NULL){
//情况2
if (pCur != _pRoot){
if (pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pRight;
else
pParent->_pRight = pCur->_pRight;
}
else
_pRoot = pCur->_pRight;
delete pCur;
pCur = NULL;
}
else if (pCur->_pRight == NULL){
//情况3
if (pCur != _pRoot){
if (pParent->_pLeft == pCur)
pParent->_pLeft = pCur->_pLeft;
else
pParent->_pRight = pCur->_pRight;
}
else
_pRoot = pCur->_pLeft;
delete pCur;
pCur = NULL;
}
else{
//情况4
Node* pParent = pCur;
Node* pDel = pCur->_pRight;
while (pDel->_pLeft){
pParent = pDel;
pDel = pDel->_pLeft;
}
pCur->_key = pDel->_key;
pCur->_value = pDel->_value;
if (pParent->_pLeft == pDel)
pParent->_pLeft = pDel->_pRight;
else
pParent->_pRight = pDel->_pR
ight;
delete pDel;
pDel = NULL;
}
return true;
}
return false;
}