具有什么特征的树是一棵二叉搜索树:
- 空树
- 若左右子树存在,左子树上的所有结点都小于根节点的值,右子树上的所有结点都大于根结点的值;左右子树也满足以上特征
根据以上特征发现二叉搜索树的中序遍历是有序的
中序遍历:1 2 3 4 5 6 7 8 9 10
查找
如果根结点不为空,则进行一下判断:
- 如果根命中,表示找到了
- 如果所要找的值小于根的值,去其左子树找
- 如果所要找的只大于根的值,去其右子树找
当走到空结点,表示没能找到需要找的结点,该结点不在该二叉搜索树中
//找到了返回0,没找到返回-1
int Search(Node *root, Key key)
{
Node *cur = root;
while (cur != NULL)
{
if (cur->key == key)
{
return 0;
}
else if (cur->key > key)
{
cur = cur->left;
}
else
{
cur = cur->right;
}
}
return -1;
}
- 递归写法
int Search_R(Node *root, Key key)
{
if (root == NULL) {
// 空树
return -1;
}
if (key == root->key) {
return 0;
}
else if (key < root->key) {
return Search_R(root->left, key);
}
else {
return Search_R(root->right, key);
}
}
插入
由于搜索二叉树要保证不存在重复元素的存在,所以在进行插入之前先要进行依次查找
- 如果元素存在,返回-1代表插入失败
- 如果不存在,根据查找算法找到空结点的上一个叶子结点就是插入结点的双亲,再根据二叉搜索树的特点来判断是双亲的左孩子还是右孩子即可,插入成功返回0
- 空树直接进行插入,此时要注意是对指向搜索二叉树的第一个结点地址的指针的值进行修改,故要传二级指针
int Insert(Node **proot, Key key)
{
Node *cur = *proot;
Node *prev = NULL;
Node *newNode = NULL;
while (cur != NULL)
{
if (cur->key == key)
{
printf("插入失败\n");
return -1;//不再重复插入
}
prev = cur;
if (cur->key > key)
{
cur = cur->left;
}
else
{
cur = cur->right;
}
}
newNode = CreateNode(key);
//空树直接插入
if (*proot == NULL)
{
*proot = newNode;//不能写成cur = newNode
}
if (key < prev->key)
{
prev->left = newNode;
}
else
{
prev->right = newNode;
}
printf("插入成功\n");
return 0;
}
- 递归写法
int Insert_R(Node **proot, Key key)
{
if (*proot == NULL) {
*proot = CreateNode(key);
return 0;
}
if (key == (*proot)->key) {
return -1;
}
if (key < (*proot)->key) {
return Insert_R(&(*proot)->left, key);
}
else {
return Insert_R(&(*proot)->right, key);
}
}
删除
删除也要先做查找,所以空树直接返回,所要删除结点不在树中也返回,如果需要删除,有以下情况
cur为所要删除结点
- 左子树为空,右子树存在
- 右子树为空,左子树存在
- 左右子树都存在
采用替换删除法,找到左子树里面值最大的那个结点,用该值替换掉所要删除结点的值
- 左右子树不存在
这种情况可以合并到第1或第2种情况当中去
int Remove(Node **proot, Key key)
{
Node *cur = *proot;
Node *prev = NULL;
Node *del = NULL;
Node *delParent = NULL;
while (cur != NULL)
{
if (cur->key == key)
{
if (cur->left != NULL && cur->right != NULL)
{
del = cur->left;
delParent = cur;
while (del->right != NULL)
{
delParent = del;
del = del->right;
}
cur->key = del->key;
if (delParent == cur)
{
cur->left = del->left;
}
else
{
delParent->right = NULL;
}
free(del);
printf("删除成功\n");
return 0;
}
else if (cur->left == NULL && cur->right != NULL)
{
if (*proot == NULL)
{
*proot = cur->right;
}
else if (key < prev->key)
{
prev->left = cur->right;
}
else
{
prev->right = cur->right;
}
free(cur);
printf("删除成功\n");
return 0;
}
else
{
if (*proot == NULL)
{
*proot = cur->left;
}
else if (key < prev->key)
{
prev->left = cur->left;
}
else
{
prev->right = cur->left;
}
free(cur);
printf("删除成功\n");
return 0;
}
}
prev = cur;
if (cur->key > key)
{
cur = cur->left;
}
else
{
cur = cur->right;
}
}
return -1;
}