二叉查找树(Binary Search Tree)
二叉搜索树(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树
那么对一个二叉搜索树的操作就有:
初始化
销毁
插入
删除
查找
searchtree.h
#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <stddef.h>
typedef char searchtreetype;
typedef struct searchtreenode{
searchtreetype data;
struct searchtreenode *lchild;
struct searchtreenode *rchild;
}searchtreenode;
void searchtreeinit(searchtreenode **root);
void searchtreedestroy(searchtreenode **root);
void searchtreeinsert(searchtreenode **root,searchtreetype value);
void searchtreeremove(searchtreenode **root,searchtreetype value);
void preorder(searchtreenode *root);
void inorder(searchtreenode *root);
我们先来做好辅助工作
void searchtreeinit(searchtreenode **root)//初始化
{
if(root == NULL)
{
return;//非法输入
}
*root = NULL;
return;
}
void searchtreedestroy(searchtreenode **root)//销毁
{
if(root == NULL)
{
return;
}
free(*root);
*root = NULL;
}
searchtreenode * creat(searchtreetype value)//创建一个节点
{
searchtreenode *newnode = (searchtreenode *)malloc(sizeof(searchtreenode));
newnode->data = value;
newnode->lchild = NULL;
newnode->rchild = NULL;
return newnode;
}
void preorder(searchtreenode *root)//两个排序便于我们测试代码
{
if(root == NULL)
{
return;
}
printf("%c",root->data);
preorder(root->lchild);
preorder(root->rchild);
}
void inorder(searchtreenode *root)
{
if(root == NULL)
{
return;
}
inorder(root->lchild);
printf("%c",root->data);
inorder(root->rchild);
}
我们在插入的时候就要知道,插入任何一个数,插完后还是一个二叉搜索树,所以在插入的时候就要和根节点比较,比根节点小,就往左边插,比根节点大,就往右边插。然后依次比较左边或者右边的根节点与我们要插入元素的大小,再做打算
下面我们来看插入的代码,我们由两种思路,递归和非递归放法
递归方法
void searchtreeinsert(searchtreenode **root,searchtreetype value)
{
if(root == NULL)
{
return;
}
if(*root == NULL)
{
searchtreenode * newnode = creat(value);
*root = newnode;
}
searchtreenode *ret = *root;
if(value > ret->data)
{
searchtreeinsert(&ret->rchild,value);
}
else if(value < ret->data)
{
searchtreeinsert(&ret->lchild,value);
}
else
{
return;
}
}
非递归方法
void searchtreeinsertbyloop(searchtreenode **root,searchtreetype value)
{
if(root == NULL)
{
return;
}
if(*root == NULL)
{
searchtreenode * newnode = creat(value);
*root = newnode;
}
searchtreenode *ret = *root;
searchtreenode *pre = NULL;//表示父节点
while(ret)
{
if(value < ret->data)
{
pre = ret;
ret = ret->lchild;
}
else if(value >ret->data)
{
pre = ret;
ret = ret->rchild;
}
else
{//相等表示插入失败
return;
}
}
if(value < pre->data)
{
pre->lchild = creat(value);
}
else
{
pre->rchild = creat(value);
}
return;
}
我们再来说查找,查找思路大致一样,都是比较,然后当他们相等的时候就把这个地址返回
递归查找
searchtreenode *searchtreefind(searchtreenode *root,searchtreetype value)
{
if(root == NULL)
{
return NULL;
}
if(value < root->data)
{
return searchtreefind(root->lchild,value);
}
else if(value > root->data)
{
return searchtreefind(root->rchild,value);
}
else
{
return root;
}
}
非递归查找
searchtreenode *searchtreefindbyloop(searchtreenode *root,searchtreetype value)
{
if(root == NULL)
{
return;
}
searchtreenode *cur = root;
while(cur)
{
if(value < cur->data)
{
cur = cur->lchild;
}
else if(value > cur->data)
{
cur = cur->rchild;
}
else
{
return cur;
}
}
return NULL;
}
下面我们进入删除的操作,删除,首先我们就要先找到要删除的位置在哪里,当我们找到要删的位置后,就会遇到四种情况
该节点没有左右子树
该节点只有左子树
该节点只有右子树
该节点左右子树都有
下面就是具体的代码实现
递归实现
void searchtreeremove(searchtreenode **root,searchtreetype value)
{
if(root == NULL)
{
return;
}
if(*root == NULL)
{
return;
}
searchtreenode *cur = *root;
if(value < cur->data)
{
return searchtreeremove(&cur->lchild,value);
}
else if(value > cur->data)
{
return searchtreeremove(&cur->rchild,value);
}
else
{
if(cur->lchild == NULL && cur->rchild == NULL)
{
*root = NULL;
free(cur);
cur = NULL;
return;
}
else if(cur->lchild != NULL && cur->rchild == NULL)
{
*root = cur->lchild;
free(cur);
cur = NULL;
return;
}
else if(cur->lchild == NULL && cur->rchild != NULL)
{
*root = cur->rchild;
free(cur);
cur = NULL;
return;
}
else
{
searchtreenode *min = cur->rchild;
while(min->lchild != NULL)
{
min = min->lchild;
}
cur->data = min->data;
searchtreeremove(&cur->rchild,min->data);
free(min);
min = NULL;
return;
}
}
}
非递归实现
void searchtreeremovebyloop(searchtreenode **root,searchtreetype value)
{
if(root == NULL)
{
return;
}
if(*root == NULL)
{
return;
}
searchtreenode *to_remove = *root;
searchtreenode *parent = NULL;
while(to_remove != NULL)
{
if(value > to_remove->data)
{
parent = to_remove;
to_remove = to_remove->rchild;
}
else if(value < to_remove->data)
{
parent = to_remove;
to_remove = to_remove->lchild;
}
else
{
break;
}
}
if(to_remove == NULL)
{
return;//没找到
}
if(to_remove->lchild == NULL && to_remove->rchild == NULL)
{
if(value < parent->data)
{
parent->lchild = NULL;
}
else
{
parent->rchild = NULL;
}
free(to_remove);
to_remove = NULL;
return;
}
else if(to_remove->lchild != NULL &&to_remove->rchild == NULL)
{
if(value < parent->data)
{
parent->lchild = to_remove->lchild;
}
else
{
parent->rchild = to_remove->lchild;
}
free(to_remove);
to_remove = NULL;
return;
}
else if(to_remove->lchild == NULL &&to_remove->rchild != NULL)
{
if(value < parent->data)
{
parent->lchild = to_remove->rchild;
}
else
{
parent->rchild = to_remove->rchild;
}
free(to_remove);
to_remove = NULL;
return;
}
else
{
searchtreenode *min = to_remove->rchild;
while(min->lchild != NULL)
{
parent = min;
min = min->lchild;
}
to_remove->data = min->data;
parent->lchild = NULL;
free(min);
min = NULL;
return;
}
}