/*********************************************************************
测试数据:二叉排序树为11 8 16 7 9 15 17 二叉排序树为11 8 16 7 10 9 15 17
11 11
/ \ / \
8 16 8 16
/ \ / \ / \ / \
7 9 15 17 7 10 15 17
先序遍历结果为:11 8 7 9 16 15 17 /
删除11之后先序遍历为:9 8 7 16 15 17 9
9 先序遍历结果为:11 8 7 10 9 16 15 17
/ \ 删除11之后先序遍历为:10 8 7 9 16 15 17
8 16 10
/ / \ / \
7 15 17 8 16
/ \ / \
7 9 15 17
***********************************************************************/
#include <stdio.h>
#include <stdlib.h>
#define ENDKEY 0
typedef int KeyType;
typedef struct node
{
KeyType key ; /* 关键字的值 */
struct node *lchild,*rchild; /* 二叉树的左右孩子指针 */
}BSTNode, *BSTree;
void InsertBST(BSTree *t, KeyType key)
/* 若在二叉排序树中不存在关键字等于key的元素,插入该元素 */
{
BSTree s;
if (*t == NULL) /* 递归结束条件 */
{
s=(BSTree)malloc(sizeof(BSTNode)); /* 申请新的结点s的堆空间 */
s->key = key;
s->lchild = NULL;
s->rchild = NULL;
*t=s;
}
else
if (key < (*t)->key)
InsertBST(&((*t)->lchild), key);/* 若插入的key的值小于根节点,则将s插入左子树 */
else
InsertBST(&((*t)->rchild), key); /* 反之,将s插入右子树 */
}
/******生成二叉排序树******/
void CreateBST(BSTree *t)
{
KeyType key;
*t = NULL;
scanf("%d", &key);
while (key != ENDKEY) /* 出口条件,ENDKEY预定义为0 */
{
InsertBST(t, key);
scanf("%d", &key);
}
}
void PreOrder(BSTree root) /* 递归先序遍历二叉树, root为指向二叉树根结点的指针 */
{
if (root != NULL)
{
printf("%d ", root->key); /* 输出结点 */
PreOrder(root->lchild); /* 先序遍历左子树 */
PreOrder(root->rchild); /* 先序遍历右子树 */
}
}
BSTree SearchBST(BSTree bst, KeyType key)
/*在根指针bst所指二叉排序树bst上,查找关键字等于key的结点,若查找成功,返回指向该元素结点指针,否则返回空指针*/
{
BSTree q;
q = bst;
while(q)
{
if (q->key == key)
return q; /* 查找成功 */
if (q->key > key)
q=q->lchild; /* 在左子树中查找 */
else
q=q->rchild; /* 在右子树中查找 */
}
return NULL; /* 查找失败 */
}
BSTNode *DelBST(BSTree t, KeyType k) /* 在二叉排序树t中删去关键字为k的结点 */
{
BSTNode *p, *f,*s ,*q;
p = t;
f = NULL;
while(p) /* 查找关键字为k的待删结点p */
{
if(p->key == k ) break; /* 找到则跳出循环 */
f = p; /* f指向p结点的双亲结点 */
if(p->key > k )
p = p->lchild;
else
p = p->rchild;
}
if(p == NULL) return t; /* 若找不到,返回原来的二叉排序树 */
/**************************************
第一种情况,当被删除的的结点p没有左子树时
此时p的位置分三种情况:
First:p为根节点
Second:p不为根,即有双亲结点,且p为双亲结点f的左子树
Third:p不为根,即有双亲结点,且p为双亲结点f的右子树
***************************************/
if(p->lchild == NULL) /* p无左子树 */
{
if(f == NULL) /* p是原二叉排序树的根 */
t = p->rchild;
else
if(f->lchild == p) /* p是f的左孩子 */
f->lchild = p->rchild ; /* 将p的右子树链到f的左链上 */
else /* p是f的右孩子 */
f->rchild = p->rchild ; /* 将p的右子树链到f的右链上 */
free(p); /* 释放被删除的结点p */
}
else /* p有左子树,即 p->lchild != NULL */
{
q = p;
s = p->lchild; /* 即左子树的最右下角的最大元素 */
while(s->rchild) /* 在p的左子树中查找最右下结点 */
{
q = s; /* q一直是s结点的前驱 */
s = s->rchild; /* s的出口条件是s->rchlid = null */
}
/***********************************************************************
找到最右下结点,由于此节点为最大值的结点,所有此节点必无右结点
*****但是对于被删除的P结点而言存在两种情况:*****
**
**
**
**
* ** *
* ** *
****
First:p的左节点不存在右孩子,如下图:(举例:删除下图的11,即被删结点p=11)
直接将p结点的左孩子指,q节点的左孩子,从而替换掉p
然后free(s),即可完成.
q==p---> 11 8
/ \ / \
s---> 8 16 7 16
/ / \ / \
7 15 17 15 17
***********************************************************************
Second:p的左节点存在右孩子(举例:删除下图的11,即被删结点p=11)
此时将q==p不成立,则将11被10替换,然后q的右孩子指向s的左孩子
(s若没有左孩子的话,情况一样,即指向null)
然后free(s),即可完成.
p---> 11 10
/ \ / \
q---> 8 16 8 16
/ \ / \ / \ / \
7 s---> 10 15 17 7 9 15 17
/
9
p---> 11 10
/ \ / \
q---> 8 16 8 16
/ \ / \ / / \
7 s---> 10 15 17 7 15 17
/
NULL
************************************************************************/
if(q == p)
q->lchild = s->lchild;
else
q->rchild = s->lchild; /*将s的左子树链到q上*/
p->key = s->key; /*将s的值赋给p*/
free(s);
}
return t;
}
void main()
{
BSTree T;
int k;
BSTree result;
printf("----输入零即退出----\n");
printf("建立二叉排序树,请输入序列:\n");
CreateBST(&T); /*创建二叉树*/
printf("先序遍历输出序列为:");
PreOrder(T);
printf("\n请输入要查找的元素:");
scanf("%d",&k);
result = SearchBST(T,k);
if (result != NULL)
printf("要查找的元素为:%d\n", result->key);
else
printf("未找到!\n");
result = DelBST(T,k); /*删除结点k*/
printf("查找完毕后,先序遍历输出序列为:");
PreOrder(result);
}
DataStructure----二叉排序树(详细)
最新推荐文章于 2022-11-07 20:21:25 发布