二叉排序树的删除与插入

#include<stdio.h>
#include<stdlib.h>
#define TRUE 1
#define FALSE 0

/* 二叉排序树的节点结构定义 */
typedef struct BiTNode
{
	int data;
	struct BiTNode *lchild, *rchild;
} BiTNode, *BiTree;


int SearchBST( BiTree T, int key, BiTree f, BiTree *p )
{
	/* 递归查找二叉排序树T中是否存在key */
	/* 指针f指向T的双亲,其初始调用值为NULL */
	/* 若查找成功,则指针p指向该数据元素节点,并返回TRUE */
	/* 否则指针p指向查找路径上访问的最后一个节点并返回FALSE */
	if( !T )
	{	
		*p = f;		//这是f唯一被用到的位置。
		return FALSE;	
	}
	else
	{
		if( key == T->data )
		{	*p = T;		return TRUE; }
		else if( key > T->data )
			return SearchBST( T->rchild, key, T, p );		/* 在右子树继续查找 */
		else	
			return SearchBST( T->lchild, key, T, p );		/* 在左子树继续查找 */
		}
}

int SearchBST2( BiTree T, int key, BiTree f, BiTree *p )
{
	/*非递归*/
	BiTree s;
	if( !T )
	{	*p = f;		return FALSE;	}
	else
	{
		while( T )
		{
			if( key == T->data )
			{	*p = T;		return TRUE;	}
			if( key > T->data )
			{	s = T;	T = T->rchild;		}
			else
			{	s = T;	T = T->lchild;		}
		}
		*p = s;
		return FALSE;
	}
}


int InsertBST1( BiTree *T, int key )
{
	/* 当二叉排序树T中不存在关键字等于key的数据元素时 */
	/* 插入key并返回TRUE,否则返回FALSE */
	/* 调用查找函数SearchBST,非递归 */
	BiTree p, s;
	if( !SearchBST2( *T, key, NULL, &p ) )
	{
		s = (BiTree)malloc(sizeof(BiTNode));
		s->data = key;
		s->lchild = s->rchild = NULL;
		if( !p )
			*T = s;				/* 插入s为根节点,此前树为空树 */
		else if( key > p->data )
			p->rchild = s;		/* 插入s为右孩子 */
		else
			p->lchild = s;		/* 插入s为左孩子 */
		return TRUE;
	}
	return FALSE;
}

int InsertBST2( BiTree *T, int key )
{
	/* 当二叉排序树T中不存在关键字等于key的数据元素时 */
	/* 插入key并返回TRUE,否则返回FALSE */
	/* 未调用查找函数,递归插入 */
	if( !(*T) )									/* 树为空, */
	{
		(*T) = (BiTree)malloc(sizeof(BiTNode));	/* 这个位置要留心,要重新分配空间,*T为空,说明未曾分配空间 */
		(*T)->data = key;
		(*T)->lchild = (*T)->rchild = NULL;
		return TRUE;
	}
	if( key == (*T)->data )
		return FALSE;
	if( key > (*T)->data )		
		return InsertBST2( &((*T)->rchild), key );		/* 插入右孩子 */
	else
		return InsertBST2( &((*T)->lchild), key );		/* 插入左孩子 */
}


void order(BiTree t)//中序输出  
{  
    if(t == NULL)  
        return ;  
    order(t->lchild);  
    printf("%d ", t->data);  
    order(t->rchild);  
} 

int Delete(BiTree *p)
{
	/* 从二叉排序树中删除节点p, 并重接它的左或右子树 */
	BiTree q, s;
	if(  !(*p)->lchild && !(*p)->rchild )	/* p为叶子节点 */
		*p = NULL;
	else if( !(*p)->lchild )	/* 左子树为空,重接右子树 */
	{
		q = *p;	
		*p = (*p)->rchild;
		free(q);
	}
	else if( !(*p)->rchild )	/* 右子树为空,重接左子树 */
	{
		q = *p;
		*p = (*p)->lchild;		/* 不太理解 */
		free(q);
	}
	else						/* 左右子树均不为空 */
	{
		q = *p;
		s = (*p)->lchild;
		while(s->rchild)		/* 转左,然后向右走到尽头*/
		{
			q = s;
			s = s->rchild;
		}
		(*p)->data = s->data;
		if( q != *p )				/* 判断是否执行上述while循环 */
			q->rchild = s->lchild;	/* 执行上述while循环,重接右子树 */	
		else
			q->lchild = s->lchild;	/* 未执行上述while循环,重接左子树 */
		free(s);
	}
	return TRUE;
}

int DeleteBST(BiTree *T, int key)
{
	/* 若二叉排序树T中存在关键字等于key的数据元素时,则删除该数据元素节点 */
	/* 并返回TRUE;否则返回FALSE */
	if( !(*T))
		return FALSE;	/* 不存在关键字等于key的数据元素 */
	else
	{
		if( key == (*T)->data )
			Delete(T);
		else if( key < (*T)->data)
			return DeleteBST(&(*T)->lchild, key);
		else
			return DeleteBST(&(*T)->rchild, key);
	}
}

int main()
{
	int i,len,x,xuanze;
	int a[11];
	BiTree T = NULL;   
	printf("请输入结点的个数:\n");
	scanf("%d",&len); 
	printf("请输入各个结点的值:\n");
	printf("\n");
	for( i = 0; i < len; i++ )
	    scanf("%d",&a[i]);
	for(int i=0;i<len;i++)
		InsertBST1(&T, a[i]);
	printf("\n");
	printf("操作界面:\n");
	printf("\n");
	printf("1、进行删除元素操作。(选此项请输入1)\n");
	printf("\n");
	printf("2、进行插入操作。(选此项请输入2)\n"); 
	printf("\n");
	printf("请选择你要选择的操作:\n");
	printf("\n");
	scanf("%d",&xuanze);
	//printf("删除58后,中序遍历二叉排序树:\n");
	if(xuanze==1)
	{	
		printf("请输入要删除的元素:");
		printf("\n");
		scanf("%d",&x);
		DeleteBST(&T,x);
		printf("\n");
		printf("删除后得到的序列为(按中序序列):\n");
		printf("\n");
		order(T);
		printf("\n");
	}
	if(xuanze==2)
	{
		printf("请输入要插入的元素:");
		printf("\n");
		scanf("%d",&x);
		InsertBST1(&T, x);
		 printf("插入后得到的序列为(按中序序列):\n");
		 printf("\n");	
		 order(T);
	}
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值