二叉搜索树
二叉查找树(Binary Search Tree),(又:二叉搜索树,二叉排序树)它或者是一棵空树,或者是具有下列性质的二叉树: 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值; 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值; 它的左、右子树也分别为二叉排序树。
以上摘录自百度百科,简单来说,二叉搜索树就是任意一棵树,右子树最大,接下来是根节点,最后是左子树。
所以在二叉搜索树里面查找某一个元素可以说是非常简单了。
基本操作
首先二叉搜索树,也是二叉树。所以它应该有最基本的一些操作。这里主要是创建子树,初始化二叉树,打印等。
//定义二叉树结构体,孩子表示法
typedef char SearchTreeType;
typedef struct SearchTreeNode {
SearchTreeType data;
struct SearchTreeNode* lchild;
struct SearchTreeNode* rchild;
} SearchTreeNode;
//初始化二叉搜索树
void SearchTreeInit(SearchTreeNode** pRoot); //初始化二叉搜索树
//实现
void SearchTreeInit(SearchTreeNode** pRoot) //初始化二叉搜索树
{
if(pRoot == NULL) {
return;//非法输入
}
*pRoot = NULL;
return;
}
//创建子树
//实现
SearchTreeNode* CreatTreeNode(SearchTreeType node)
{
SearchTreeNode* new_node = (SearchTreeNode*)malloc(sizeof(SearchTreeNode));
new_node->data = node;
new_node->lchild = NULL;
new_node->rchild = NULL;
return new_node;
}
//打印二叉搜索树,便于调试
//实现
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 SearchTreePrintChar(SearchTreeNode* root)
{
if(root == NULL) {
return;
}
PreOrder(root);
printf("\n");
InOrder(root);
printf("\n");
return;
}
//销毁二叉搜索树
//实现
void DestroyNode(SearchTreeNode** pRoot)
{
free(*pRoot);
*pRoot = NULL;
}
void SearchDestroy(SearchTreeNode** pRoot)//销毁二叉搜索树
{
if(pRoot == NULL) {
return;
}
if(*pRoot == NULL) {
return;
}
SearchTreeNode* root = *pRoot;
SearchDestroy(&root->lchild);
SearchDestroy(&root->rchild);
DestroyNode(&root);
return;
}
查找
//实现,递归版本的查找二叉搜索树
SearchTreeNode* SearchTreeFind(SearchTreeNode* root,
SearchTreeType to_find) //查找二叉搜索树
{
if(root == NULL) {
return NULL;
}
if(to_find < root->data) {
return SearchTreeFind(root->lchild, to_find);
} else if(to_find > root->data) {
return SearchTreeFind(root->rchild, to_find);
} else {
return root;
}
}
//非递归版本的查找二叉搜索树
SearchTreeNode* SearchTreeFindByLoop(SearchTreeNode* root,
SearchTreeType to_find) //非递归版本查找二叉搜索树
{
if(root == NULL) {
return NULL;
}
while(root != NULL) {
if(to_find > root->data) {
root = root->rchild;
} else if(to_find < root->data){
root = root->lchild;
} else {
return root;
}
}
return NULL;
}
插入
二叉搜索树的插入过程,就是一个遍历的过程。因为插入前后都要保证二叉搜索树本身的性质。所以在插入的时候应该判断插入点。所以可以用要插入的元素与二叉搜索树内部元素比较。如果比根节点小,那么再继续与根节点左子树比较,如果大,与根节点右子树比较。直至到一个合适的位置插入。
//递归实现插入
void SearchTreeInsert(SearchTreeNode** pRoot, SearchTreeType to_insert)//二叉搜索树插入
{
if(pRoot == NULL) {
return;
}
if(*pRoot == NULL) {
*pRoot = CreatTreeNode(to_insert);
return;
}
SearchTreeNode* root = *pRoot;
if(to_insert < root->data) {
SearchTreeInsert(&root->lchild, to_insert);
} if(to_insert > root->data) {
SearchTreeInsert(&root->rchild, to_insert);
} else {
return;
}
}
//非递归版本的插入
void SearchTreeInsertByLoop(SearchTreeNode** pRoot, SearchTreeType to_insert)//非递归版本二叉搜索树插入
{
if(pRoot == NULL) {
return;
}
if(*pRoot == NULL) {
*pRoot = CreatTreeNode(to_insert);
return;
}
SearchTreeNode* root = *pRoot;
SearchTreeNode* pre = NULL;
while(root != NULL) {
if(to_insert < root->data) {
pre = root;
root = root->lchild;
} else if(to_insert > root->data) {
pre = root;
root = root->rchild;
} else {
return;
}
}
if(to_insert > pre->data) {
pre->rchild = CreatTreeNode(to_insert);
} else {
pre->lchild = CreatTreeNode(to_insert);
}
return;
}
删除
删除二叉搜索树与插入相同,也需要保证删除的前后该树都是一个二叉搜索树。所以这个时候就需要讨论了。
//递归版的实现
void SearchTreeRemove(SearchTreeNode** pRoot, SearchTreeType to_remove)//删除二叉搜索树中某一个元素
{
if(pRoot == NULL) {
return;
}
if(*pRoot == NULL) {
return;
}
SearchTreeNode* root = *pRoot;
if(to_remove > root->data) {
SearchTreeRemove(&root->rchild, to_remove);
} else if(to_remove < root->data) {
SearchTreeRemove(&root->lchild, to_remove);
} else {
if(root->lchild == NULL && root->rchild == NULL) {
DestroyNode(&root);
return;
} else if(root->lchild != NULL && root->rchild == NULL) {
SearchTreeNode* cur = root;
root = root->lchild;
DestroyNode(&cur);
return;
} else if(root->lchild == NULL && root->rchild != NULL) {
SearchTreeNode* cur = root;
root = root->rchild;
DestroyNode(&cur);
return;
} else {
SearchTreeNode* min = root->rchild;
SearchTreeNode* pre = min;
while(min->lchild != NULL) {
pre = min;
min = min->lchild;
}
root->data = min->data;
pre->lchild = min->rchild;
DestroyNode(&min);
return;
}
}
}
//非递归版本的实现
void SearchTreeRemoveByLoop(SearchTreeNode** pRoot, SearchTreeType to_remove)//非递归版本删除二叉搜索树中某一个元素
{
if(pRoot == NULL) {
return;
}
if(*pRoot == NULL) {
return;
}
SearchTreeNode* root = *pRoot;
SearchTreeNode* parent = root;
while(root != NULL) {
if(to_remove > root->data) {
parent = root;
root = root->rchild;
} else if(to_remove < root->data) {
parent = root;
root = root->lchild;
} else {
break;
}
}
if(root == NULL) {
return;
}
if(root->lchild == NULL && root->rchild == NULL) {
DestroyNode(&root);
return;
} else if(root->lchild != NULL && root->rchild == NULL) {
SearchTreeNode* cur = root;
root = root->lchild;
DestroyNode(&cur);
return;
} else if(root->lchild == NULL && root->rchild != NULL) {
SearchTreeNode* cur = root;
root = root->rchild;
DestroyNode(&cur);
return;
} else {
SearchTreeNode* min = root->rchild;
SearchTreeNode* pre = min;
while(min->lchild != NULL) {
pre = min;
min = min->lchild;
}
root->data = min->data;
pre->lchild = min->rchild;
DestroyNode(&min);
return;
}
}
欢迎大家共同讨论,如有错误及时联系作者指出,并改正。谢谢大家!