二叉排序树的概念
二叉排序树(Binary Sort Tree),又称为二叉查找树,是一种特殊的二叉树。它或者是一棵空树,或者是具有下列性质的二叉树:
- 若它的左子树不空,则左子树上所有结点的值均小于它的根结点的值。
- 若它的右子树不空,则右子树上所有结点的值均大于它的根结点的值。
- 它的左、右子树也分别为二叉排序树。
换句话说,二叉排序树中,每个节点的值都大于其左子树中任意节点的值,且小于其右子树中任意节点的值。
二叉排序树的结构
typedef struct BST_Node
{
struct BST_Node* Left; // 指向当前节点左孩子
struct BST_Node* Right; // 指向当前节点右孩子
char data; // 当前节点数据域
}BST_Node, * BST_Tree;
建立二叉树
void CreateBST(BST_Tree* T, int a[], int n)
{
for (int i = 0; i < n; i++)
{
InsertBST(T, a[i]);
}
}
插入结点
插入新元素时,可以从根节点开始,遇键值较大者就向左,遇键值较小者就向右,一直到叶子节点在进行插入。
void InsertBST(BST_Tree* root, int value)
{
//如果没有就创建
if (!(*root))
{
*root = malloc(sizeof(BST_Node));
if (!*root) exit(-1);
(*root)->data = value;
(*root)->Left = (*root)->Right = NULL;
return;
}
if (value > (*root)->data)
InsertBST(&((*root)->Right), value);
else if (value < (*root)->data)
InsertBST(&((*root)->Left), value);
else
return;
}
查找
查找最小
从根节点一直往左走,直到最左边的就是最小
BST_Tree SerchMin(BST_Tree root)
{
if (!root)
return NULL;
if (!(root->Left))
return root;
else
return SerchMin(root->Left);
}
查找最大
从根节点一直往右走,直到最右边的就是最小
BST_Tree SerchMax(BST_Tree root)
{
if (!root)
return NULL;
if (!(root->Right))
return root;
else
return SerchMax(root->Right);
}
查找
从根节点出发,遇到键值大的节点就向这个节点的左孩子方向查找,遇到键值小的就向则个节点的右孩子方向查找。
BST_Tree Search(BST_Tree root,int value)
{
if (root == NULL)
return NULL;
if (value > root->data) //查找右子树
return Search(root->Left, value);
else if (value < root->data) //查找左子树
return Search(root->Right, value);
else
return root;
}
删除
1 若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
2 若p没有左子树,直接用p的右孩子取代它。
有些资料在删除的时候是分叶子结点,非叶子结点(一个孩子),非叶子结点(两个孩子),根结点讨论
BST_Tree DeleteNode(BST_Tree p)
{
if (p->Left)
{
BST_Tree r = p->Left;
while (r->Right)
{
r = r->Right;
}
r->Right = p->Right;
BST_Tree t=malloc(sizeof(BST_Node));
t = p->Left;
free(p);
return t;
}
else
{
BST_Tree t=malloc(sizeof(BST_Node));
t = p->Right;
free(p);
return t;
}
}
BST_Tree DeleteTree(BST_Tree* p, int x)
{
if (!(*p))
return NULL;
else
{
if (x == (*p)->data)
(*p) =DeleteNode((*p));
else if (x > (*p)->data)
(*p)->Right=DeleteTree((*p)->Right, x);
else
(*p)->Left=DeleteTree((*p)->Left, x);
}
return (*p);
}
注意
DeleteTree的参数是BST_Tree的指针,因为只有传入指针才能实现对传入参数的真正的修改。
也可以不用传人指针,不过要接收函数的返回值。
int a[13] = { 23,26,4,44,32,17,20,13,14,15,45,1,5 };
BST_Tree tree=NULL;
CreateBST(&tree, a, 13);
/*tree=DeleteTree(tree,23);
DeleteTree(&tree,23);*/
遍历
前序遍历
void PreOrderTraversal(BST_Tree Tree)
{
if (!Tree)
return;
else
{
printf("%3d", Tree->data);
PreOrderTraversal(Tree->Left);
PreOrderTraversal(Tree->Right);
}
}
中序遍历
void InOrderTraversal(BST_Tree Tree)
{
if (!Tree)
return;
else
{
InOrderTraversal(Tree->Left);
printf("%3d", Tree->data);
InOrderTraversal(Tree->Right);
}
}
后序遍历
void PostOrderTraversal(BST_Tree Tree)
{
if (!Tree)
return;
else
{
PostOrderTraversal(Tree->Left);
PostOrderTraversal(Tree->Right);
printf("%c ", Tree->data);
}
}
删除测试
删除叶子结点5
运行结果
没问题,符合要求
删除结点26
若p没有左子树,直接用p的右孩子取代它。
运行结果
没问题,符合要求
删除节点17
若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
运行结果
没问题,符合要求
删除根结点
若p有左子树,找到其左子树的最右边的叶子结点r,把p的右子树作为r的右子树;用p的左孩子取代p;
运行结果
没问题,符合要求