二叉搜索树(Binary Search Tree)的性质:
1、每个节点都有一个作为搜索关键码的key,并且所有节点的key都不相同。
2、左子树上的key值都小于根节点的key值。
3、右子树上的key值都大于根节点的key值。
4、左右子树都是二叉搜索树。
如下图为一颗二叉搜索树
实现:
二叉搜索树的插入:
二叉树的插入是根据要插入节点的key值找一个合适的位置插入节点,如果要插入节点的key值大于当前结点的key值,则向右树寻找合适的位置,如果要插入节点的key值小于当前结点的key值,则向左树寻找合适的位置,如果要插入的节点的key值等于当前结点的key值,则说明该节点已存在,直接返回,不进行插入。
代码实现:
bool Insert(int key)//插入-非递归
{
Node * cur = _root;
Node * parent = NULL;
while(cur)
{
if(cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else //cur->_key==key 节点存在
{
return false;
}
}
cur = new Node(key);
if (parent == NULL)
{
_root = cur;
}
else
{
if (parent->_key > key)
{
parent->_left = cur;
}
else
{
parent->_right = cur;
}
}
return true;
}
bool InsertR(int key)//插入-递归
{
return _InsertR(_root, key);
}
bool _InsertR(Node *& root, int key)//插入-递归
{
if (root == NULL)
{
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;
}
}
}
二叉搜索树的查找类似于二分查找,如果要查找节点的key值大于当前结点的key值,则向右树查找,如果要插入节点的key值小于当前结点的key值,则向左树查找,如果要插入的节点的key值等于当前结点的key值,则返回该节点。若走到一个空的位置还没有该节点,则说明节点不存在。
代码实现:
Node* Find(int key)//查找-非递归
{
Node *cur = _root;
while (cur)
{
if (cur->_key < key)
{
cur = cur->_right;
}
else if(cur->_key>key)
{
cur = cur->_left;
}
else
{
return cur;
}
}
return NULL;
}
Node * FindR(int key)//查找-递归
{
return _FindR(_root, key);
}
Node* _FindR(Node *& root, int key)//查找-递归
{
while (root)
{
if (root->_key == key)
{
return root;
}
else if (root->_key > key)
{
return _FindR(root->_left,key);
}
else
{
return _FindR(root->_right, key);
}
}
return NULL;
}
二叉搜索树的删除分四种情况:删除叶子结点、要删除的节点无左孩子、要删除的节点无右孩子、要删除的节点既有左孩子也有右孩子。在实际操作中删除叶子节点可以归为要删除的节点无左孩子或无右孩子里面,因此,其实删除就只有三种情况了,下面我画图来说明这三种删除的处理方法。
代码实现:
bool Remove(int key)//删除-非递归
{
Node * cur = _root;
Node * parent = NULL;
Node *del = NULL;
while (cur)
{
if (cur->_key < key)
{
parent = cur;
cur = cur->_right;
}
else if (cur->_key > key)
{
parent = cur;
cur = cur->_left;
}
else
{
if (cur->_left == NULL)//左为空or叶子结点
{
del = cur;
if (cur == _root)//parent==NULL删除根节点
{
_root = cur->_right;
}
else if (parent->_left==cur)
{
parent->_left = cur->_right;
}
else
{
parent->_right = cur->_right;
}
}
else if (cur->_right == NULL)//右为空
{
del = cur;
if (cur == _root)//删除根节点
{
_root = cur->_left;
}
else if (parent->_left == cur)
{
parent->_left = cur->_left;
}
else
{
parent->_right = cur->_left;
}
}
else//左右都不为空
{
//找右孩子的最左节点替换该节点
Node * subLeft = cur->_right;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
del = subLeft;
cur->_key = subLeft->_key;
if (subLeft == cur->_right)//cur->_right无左孩子
{
cur->_right = subLeft->_right;
}
else
{
parent->_left = subLeft->_right;
}
}
delete del;
del = NULL;
return true;
}
}
return false;
}
bool RemoveR(int key)//删除-递归
{
return _RemoveR(_root,key);
}
bool _RemoveR(Node * &root,int key)//删除-递归
{
while (root)
{
if (root->_key > key)
{
return _RemoveR(root->_right, key);
}
else if (root->_key < key)
{
return _RemoveR(root->_left, key);
}
else
{
Node *parent = NULL;
Node * del = NULL;
if (root->_left == NULL)//左为空or叶子结点
{
del = root;
if (root == _root)//parent==NULL删除根节点
{
_root = root->_right;
}
else if (parent->_left == root)
{
parent->_left = root->_right;
}
else
{
parent->_right = root->_right;
}
}
else if (root->_right == NULL)//右为空
{
del = root;
if (root == _root)//删除根节点
{
_root = root->_left;
}
else if (parent->_left == root)
{
parent->_left = root->_left;
}
else
{
parent->_right = root->_left;
}
}
else//左右都不为空
{
//找右孩子的最左节点替换该节点
Node * subLeft = root->_right;
while (subLeft->_left)
{
parent = subLeft;
subLeft = subLeft->_left;
}
del = subLeft;
root->_key = subLeft->_key;
if (subLeft == root->_right)//cur->_right无左孩子
{
root->_right = subLeft->_right;
}
else
{
parent->_left = subLeft->_right;
}
}
delete del;
del = NULL;
return true;
}
}
return false;
}
完整代码已托管至github,需要的请点击以下链接:https://github.com/Sunxy7/PracticeCode/tree/master/SearchBinaryTree