二叉搜索树又称二叉排序树,它或者是一棵空树,或者具有以下性质的树:
- 若它的左子树不为空,则左子树上所有节点的值都小于根节点的值
- 若它的右子树不为空,则右子树上所有节点的值都大于根节点的值
- 它的左右子树也分别为二叉搜索树
注意:搜索二叉树中没有相同的值。
因为搜索二叉树结构的特殊性,左子树永远比根节点小,右子树永远比根节点大,所以中序遍历一次二叉树,就可以得到一个升序的有序序列。
算法实现:
- 搜索二叉树的查找
- 在搜索二叉树插入结点(递归与非递归)
- 在搜索二叉树删除结点(递归与非递归)
- 搜索二叉树的销毁
【1】二叉树的查找算法:
在树tree中查找某一个数值data,若tree是空树,则查找失败
若data大于tree的根节点值,则递归到tree的右子树查找
若data小于tree的根节点值,则递归到tree的左子树查找
若data等于tree的根节点值,则查找成功。
【2】搜索二叉树的插入算法:
首先执行查找算法,找出被插结点的父亲结点。
判断被插结点是其父亲结点的左、右孩子。将被插结点作为叶子结点插入。
若二叉树为空。则首先单独生成根结点
【3】搜索二叉树的删除算法:
首先查找元素是否在二叉搜索树中,如果不存在,则返回,
否则可分为四种情况:
- 1.要删除的结点无孩子结点
- 2.要删除的结点只有左孩子结点
- 3.要删除的结点只有右孩子结点
- 4.要删除的结点有左、右孩子结点
情况1可以归类到2或者3 ,对应的执行步骤:
a. 直接删除该结点
b. 删除该结点且使被删除节点的双亲结点指向被删除节点的左孩子结点
c. 删除该结点且使被删除节点的双亲结点指向被删除结点的右孩子结点
d. 在它的右子树中寻找中序下的第一个结点(关键码最小),用它的值填补到被删除节点中,在来处理该结点的删除问题
#include"BinarySearchTree.h"
#include<stdio.h>
#include<assert.h>
#include<windows.h>
#include<malloc.h>
typedef int DataType;
typedef struct BinarySearchTreeNode
{
struct BinarySearchTreeNode* _left;
struct BinarySearchTreeNode* _right;
DataType data;
}BSTreeNode;
BSTreeNode *BuyBSTreeNode(DataType x);//创建节点
int BSTreeNodeInsert(BSTreeNode** tree, DataType data);
int BSTreeNodeInsertR(BSTreeNode** tree, DataType data);//递归插入
const BSTreeNode* BSTreeNodeFind(BSTreeNode* tree, DataType data);//查找
int BSTreeRemove(BSTreeNode** tree, DataType data);
int BSTreeRemoveR(BSTreeNode** tree, DataType data);//递归删除
void BSTreeDestory(BSTreeNode** tree);//销毁搜索二叉树
void BSTreeInOrder(BSTreeNode* tree);//中序遍历
TestBSTree.c
#include"BinarySearchTree.h"
void BSTreeInOrder(BSTreeNode* tree)//中序遍历
{
if (NULL == tree)
return;
BSTreeInOrder(tree->_left);
printf("%d ", tree->data);
BSTreeInOrder(tree->_right);
}
BSTreeNode* BuyBSTreeNode(DataType data)
{
BSTreeNode* node = (BSTreeNode*)malloc(sizeof(BSTreeNode));
assert(node);
node->data = data;
node->_left = NULL;
node->_right = NULL;
return node;
}
//成功返回0,失败返回-1
int BSTreeNodeInsertR(BSTreeNode** tree, DataType data)//递归
{
if (*tree == NULL)
{
*tree = BuyBSTreeNode(data);
return 0;
}
if ((*tree)->data > data)
return BSTreeNodeInsertR(&(*tree)->_left, data);
else if ((*tree)->data < data)
return BSTreeNodeInsertR(&(*tree)->_right, data);
else
return -1;
}
int BSTreeNodeInsert(BSTreeNode** tree, DataType data)//非递归
{
if (*tree == NULL)
{
*tree = BuyBSTreeNode(data);
return 0;
}
BSTreeNode* cur = *tree;
BSTreeNode* parent = *tree;
while (cur)
{
parent = cur;
if (parent->data > data)//左树
{
cur = cur->_left;
}
else if (parent->data < data)//右树
{
cur = cur->_right;
}
else
return -1;
}
//树里没有相同数据,插入,判断所插位置
if (parent->data > data)//如果数据小于父亲,向父亲节点的左树链接
parent->_left = BuyBSTreeNode(data);
else
parent->_right = BuyBSTreeNode(data);
return 0;
}
const BSTreeNode* BSTreeNodeFind(BSTreeNode* tree, DataType data)
{
assert(tree);
while (tree)
{
if (tree->data == data)
return tree;
else if (tree->data > data)
tree = tree->_left;
else
tree = tree->_right;
}
return NULL;
}
int BSTreeRemove(BSTreeNode** tree, DataType data)
{
if ((*tree) == NULL)
return NULL;
BSTreeNode* cur = *tree;
BSTreeNode* parent = *tree;
BSTreeNode* del = NULL;
BSTreeNode* sub = NULL;
//1.左为空
//2.右为空
//3.左右不为空
while (cur)
{
if (cur->data < data)
{
parent = cur;
cur = cur->_right;
}
else if (cur->data > data)
{
parent = cur;
cur = cur->_left;
}
//已经找到被删除节点cur
else
{
del = cur;
if (cur->_left == NULL)//左孩子空
{
if (parent->_left == cur)
parent->_left = cur->_right;
else if (parent->_right == cur)
parent->_right = cur->_right;
else if (parent == cur)//所删节点无孩子
*tree = parent->_right;
cur = NULL;//删除后要跳出循环
}
else if (cur->_right == NULL)//右孩子为空
{
if (parent->_right == cur)
parent->_right = cur->_left;
else if (parent->_left == cur)
parent->_left = cur->_left;
else if (parent == cur)
*tree = parent->_left;
cur = NULL;
}
else//左右孩子都不为空
{
sub = cur;
del = cur->_right;
while (del->_left)
{
sub = del;
del = del->_left;
}
cur->data = del->data;
if (sub->_right == del)
sub->_right = del->_right;
else
sub->_left = del->_right;
}
}
}
free(del);
del = NULL;
return 0;
}
int BSTreeRemoveR(BSTreeNode** tree, DataType data)
{
if (NULL == *tree)
return -1;
if ((*tree)->data > data)
return BSTreeRemoveR(&(*tree)->_left, data);
else if ((*tree)->data < data)
return BSTreeRemoveR(&(*tree)->_right, data);
else//找到删除的节点
{
BSTreeNode* del = *tree;
if ((*tree)->_left == NULL)//左空
*tree = (*tree)->_right;
else if ((*tree)->_right == NULL)//右空
*tree = (*tree)->_left;
else//左右都不为空
{
BSTreeNode* sub = (*tree);
del = (*tree)->_right;
while (del->_left)
{
sub = del;
del = del->_left;
}
(*tree)->data = del->data;
if (sub->_right == del)
sub->_right = del->_right;
else
sub->_left = del->_right;
}
free(del);
del = NULL;
}
return 0;
}
void BSTreeDestory(BSTreeNode** tree)//销毁
{
if ((*tree)->_left != NULL)
BSTreeDestory(&(*tree)->_left);
else if ((*tree)->_right != NULL)
BSTreeDestory(&(*tree)->_right);
free(*tree);
*tree = NULL;
}
test.c
#include"BinarySearchTree.h"
int main()
{
BSTreeNode* tree = NULL;
BSTreeNodeInsert(&tree, 5);
BSTreeNodeInsert(&tree, 1);
BSTreeNodeInsert(&tree, 2);
BSTreeNodeInsert(&tree, 3);
BSTreeNodeInsert(&tree, 4);
BSTreeNodeInsert(&tree, 6);
BSTreeNodeInsert(&tree, 0);
BSTreeNodeInsert(&tree, 7);
BSTreeNodeInsert(&tree, 8);
BSTreeNodeInsert(&tree, 9);
BSTreeInOrder(tree);
printf("\n");
const BSTreeNode* cur = BSTreeNodeFind(tree, 7);
printf("查找7?%d\n",cur->data );
BSTreeRemove(&tree, 4);
BSTreeRemove(&tree, 8);
BSTreeRemove(&tree, 3);
BSTreeRemove(&tree, 7);
BSTreeRemove(&tree, 5);
BSTreeInOrder(tree);
printf("\n");
BSTreeRemove(&tree, 0);
BSTreeRemove(&tree, 1);
BSTreeRemove(&tree, 2);
BSTreeRemove(&tree, 3);
BSTreeRemove(&tree, 4);
BSTreeRemove(&tree, 5);
BSTreeRemove(&tree, 6);
BSTreeRemove(&tree, 7);
BSTreeRemove(&tree, 8);
BSTreeRemove(&tree, 9);
BSTreeInOrder(tree);
printf("\n");
BSTreeDestory(&tree);
system("pause");
return 0;
}
搜索二叉树的应用:
模拟实现一个简单的中英互译的字典
判断一个单词是否拼写正确