1. 简述
最近打算复习一下,几个经典的树结构,本文主要关注二叉搜索树,英文名称为Binary Search Tree (简称BST)。
本文主要总结二叉搜索树的查找算法、插入算法和删除算法。
2. 查找算法
这个比较简单,要么找到了,要么向左,要么向右。
BSTNode
*
bst_search(BSTNode
*
node,
int
value) {
while (node != NULL) {
if (value < node -> value) // 向左
node = node -> left;
else if (value > node -> value) // 向右
node = node -> right;
else // 找到
return node;
}
return NULL; // 失败
}
while (node != NULL) {
if (value < node -> value) // 向左
node = node -> left;
else if (value > node -> value) // 向右
node = node -> right;
else // 找到
return node;
}
return NULL; // 失败
}
3. 插入算法
这个也不难,首先找到插入的位置,要么向左,要么向右,直到找到空结点,即为插入位置,如果找到了相同值的结点,插入失败。
bool
bst_insert(BSTNode
*&
root,
int
value) {
BSTNode* pre = NULL;
BSTNode* pre = NULL;
BSTNode* curr = root;
while (curr != NULL) {
if (value < curr -> value) { // 向左
pre = curr;
curr = curr -> left;
while (curr != NULL) {
if (value < curr -> value) { // 向左
pre = curr;
curr = curr -> left;
}
else if (value > curr -> value) { // 向右
pre = curr;
curr = curr -> right;
else if (value > curr -> value) { // 向右
pre = curr;
curr = curr -> right;
}
else // 失败
return false ;
}
curr = new BSTNode; // 插入
curr -> value = value;
curr -> left = curr -> right = NULL;
if(pre == NULL)
else // 失败
return false ;
}
curr = new BSTNode; // 插入
curr -> value = value;
curr -> left = curr -> right = NULL;
if(pre == NULL)
root = curr;
else
else
curr->value < pre->value ? pre->left=curr : pre->right=curr;
return true ;
}
return true ;
}
4. 删除算法
相对查找和插入复杂一点,根据待删除结点的孩子情况,分三种情况:没有孩子,只有一个孩子,有两个孩子。
没有孩子的情况,其父结点指向空,删除该结点。
有一个孩子的情况,其父结点指向其孩子,删除该结点。
有两个孩子的情况,当前结点与左子树中最大的元素交换,然后删除当前结点。左子树最大的元素一定是叶子结点,交换后,当前结点即为叶子结点,删除参考没有孩子的情况。另一种方法是,当前结点与右子树中最小的元素交换,然后删除当前结点。
代码实现分别考虑三种情况,并且每种情况考虑了待删除结点是不是根结点。虽然实现啰嗦了一些,不过情况考虑的周全,对于入门算是够了。
bool
bst_delete(BSTNode
*&
node,
int
value) {
BSTNode * parent = NULL;
BSTNode * tmp;
while (node != NULL) {
if (value < node -> value) { // 向左
parent = node;
node = node -> left;
}
else if (value > node -> value) { // 向右
parent = node;
node = node -> right;
}
else { // 找到了
if (NULL == node -> left && NULL == node - right) { // 叶子结点
if (parent == NULL) { // 根结点
delete node;
node = NULL;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = NULL):(parent -> right = NULL);
delete node;
node = NULL;
}
}
else if (NULL != node -> left && NULL == node -> right) { // 只有左孩子
if (parent == NULL) { // 根结点
tmp = node;
node = node -> left;
delete tmp;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = node -> left):(parent -> right = node -> left);
delete node;
}
}
else if (NULL != node -> right && NULL == node -> left) { // 只有右孩子
if (parent == NULL) { // 根结点
tmp = node;
node = node -> right;
delete tmp;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = node -> right):(parent -> right = node -> right);
delete node;
}
}
else { // 既有左孩子也有右孩子
BSTNode * leftNode = node;
while (leftNode -> right != NULL) {
parent = leftNode;
leftNode = leftNode -> right;
}
// 交换leftNode与node
int swapValue = leftNode -> value;
leftNode -> value = node -> value;
node -> value = swapValue;
// 删除leftNode,parent肯定不为空
(parent -> left == node) ? (parent -> left = NULL):(parent -> right = NULL);
delete node;
}
}
}
return false ; // 失败
}
BSTNode * parent = NULL;
BSTNode * tmp;
while (node != NULL) {
if (value < node -> value) { // 向左
parent = node;
node = node -> left;
}
else if (value > node -> value) { // 向右
parent = node;
node = node -> right;
}
else { // 找到了
if (NULL == node -> left && NULL == node - right) { // 叶子结点
if (parent == NULL) { // 根结点
delete node;
node = NULL;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = NULL):(parent -> right = NULL);
delete node;
node = NULL;
}
}
else if (NULL != node -> left && NULL == node -> right) { // 只有左孩子
if (parent == NULL) { // 根结点
tmp = node;
node = node -> left;
delete tmp;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = node -> left):(parent -> right = node -> left);
delete node;
}
}
else if (NULL != node -> right && NULL == node -> left) { // 只有右孩子
if (parent == NULL) { // 根结点
tmp = node;
node = node -> right;
delete tmp;
}
else { // 非根结点
(parent -> left == node) ? (parent -> left = node -> right):(parent -> right = node -> right);
delete node;
}
}
else { // 既有左孩子也有右孩子
BSTNode * leftNode = node;
while (leftNode -> right != NULL) {
parent = leftNode;
leftNode = leftNode -> right;
}
// 交换leftNode与node
int swapValue = leftNode -> value;
leftNode -> value = node -> value;
node -> value = swapValue;
// 删除leftNode,parent肯定不为空
(parent -> left == node) ? (parent -> left = NULL):(parent -> right = NULL);
delete node;
}
}
}
return false ; // 失败
}
5. 参考
百度百科_二叉搜索树 http://baike.baidu.com/view/389453.htm