算法基础(七):二叉排序树基本操作-插入、删除(附源代码加注释)

#include"stdafx.h"
#include"Basic_Symbol.h"


#define MaxSize 100
typedef int KeyType;		//定义关键字类型
typedef char InfoType;		
typedef struct node			//定义结点类型
{
	KeyType key;			//关键字项
	InfoType data;			//数据域
	struct node
		*lchild,
		*rchild;			//左右孩子指针
}BSTNode;
//全局变量
KeyType predt = -32767;				//保存中序节点前驱的值
int path[MaxSize];					//全局变量,用于存放路径

void DispBST(BSTNode *b);	//函数声明

int InsertBST(BSTNode *&p, KeyType k)			//P为根节点,插入关键字为K的结点
{
	if( p == NULL)								//如果原树为空,则操作
	{
		p = (BSTNode *)malloc(sizeof(BSTNode)); //分配空间
		p->key = k;
		p->lchild = p->rchild = NULL;			//左右孩子初值为空
		return 1;
	}
	else if(k == p->key)						//如果等于,则return,因为二叉排序树里面不会有两个相等的数字
		return 0;
	else if(k < p->key)							//如果小于,则放左边,要深刻理解递归,代码便写的自然
		return InsertBST(p->lchild,k);
	else return InsertBST(p->rchild,k);			//大于,放右边,满足二叉排序树的特点
}

BSTNode *CreatBST(KeyType A[],int n)			//利用数组A中的元素作为关键字来构造二叉树,n为要建立的结点个数,应小于数组长度
{
	BSTNode *bt = NULL;
	int i = 0;
	while(i< n)									//循环加递归构造二叉排序树
		if(InsertBST(bt,A[i]) == 1)
		{
			printf("\nthe number %d step:",i+1,A[i]);
			DispBST(bt);
			i++;
		}
	return bt;									//返回根指针
}

void Delete1(BSTNode *p,BSTNode *&r)			//当被删除结点p有左右子树时的删除过程
{
	BSTNode *q;
	if(r->rchild != NULL)		//如果右孩子不为空
	{
		Delete1(p,r->rchild);	//递归找到最右下节点,为什么要找最右下节点了,因为最右下节点是这棵树中最大的。
	}
	else						//找到了最右下
	{
		p->key = r->key;		//将r的关键字赋值给p,这是必须的,只有r的关键字(x)可以来胜任..x是左边的树中最大的但是小于p->key,更小于p的右子树。
		q = r;					
		r = r->lchild;			//r的值被r左孩子代替
		free(q);				//释放空间
	}
}
void Delete( BSTNode *&p)		//从二叉排序树中删除*p结点,这是在已经找到了要删除的节点时调用的,在DeleteBST中被调用
{
	BSTNode *q;
	if(p->rchild == NULL)		//没有右子树的情况
	{
		q = p;
		p = p->lchild;			//p指向的内存空间被释放,显然此时p退居到左孩子位置,哈哈!画个图图看看更清晰哈
		free(q);
	}
	else if(p->lchild == NULL)	//没有左子树,同样的道理..
	{
		q = p;
		p = p->rchild;
		free(q);
	}
	else Delete1(p,p->lchild);	//左右都有的话,调用DELETE1函数来处理该情况
}
int DeleteBST(BSTNode *&bt,KeyType k)		//在bt中删除关键字为k的结点
{
	if(bt == NULL)
		return 0;							//空树,删除失败
	else
	{
		if(k < bt->key)
			return DeleteBST(bt->lchild,k);
		else if(k>bt->key)
			return DeleteBST(bt->rchild,k);
		else 
		{
			Delete(bt);
			return 1;
		}
	}
}
void SearchBST1(BSTNode *bt,KeyType k,KeyType path[],int i)		//以非递归方式输出路径
{
	int j;
	if(bt == NULL)			
		return;
	else if(k == bt->key)						//找到了
	{
		path[i+1] = bt->key;					//将节点的值保存在路径中
		for(j = 0;j<=i+1;j++)
			printf("%3d",path[j]);				//输出
		printf("\n");
	}
	else										//没找到
	{
		path[i + 1] = bt->key;					//将节点的值保存在路径中,下面更具情况继续找
		if(k < bt->key)							//如果k小于当前值
			SearchBST1(bt->lchild,k,path,i+1);  //则进入左子树找,这是根据二叉排序树的特点来的
		else 
			SearchBST1(bt->rchild,k,path,i+1);	//大的话。进入右边找。其实找,还是在递归,只是把路径保存在一个可爱的数组中而已
	}
}
int SearchBST2(BSTNode *bt,KeyType k)			//递归输出路径,就要简单的多了,但是理解不是很容易,递归太重要了,对吧!
{
	if(bt == NULL)
		return 0;
	else if(k == bt->key)
	{
		printf("%3d",bt->key);
		return 1;
	}
	else if(k < bt->key)
		SearchBST2(bt->lchild,k);
	else SearchBST2(bt->rchild,k);
	printf("%3d",bt->key);
}
void DispBST(BSTNode *bt)								//括号表示法输出二叉排序树
{
	if(bt != NULL)
	{
		printf("%d",bt->key);							//输出根节点的值
		if(bt->lchild != NULL || bt->rchild != NULL)	//如果左右孩子不为空,输出他们的key值
		{
			printf("(");
			DispBST(bt->lchild);
			if(bt->rchild != NULL)
				printf(",");
			DispBST(bt->rchild);
			printf(")");
		}
	}
}


int JudgeBST(BSTNode *bt)				//判断是否是二叉排序树
{
	int b1,b2;							 
	if(bt == NULL)						//空则返回
		return 1;
	else
	{
		b1 = JudgeBST(bt->lchild);		//递归得到最左下的节点
		if(b1 == 0 || predt >= bt->key) //如果左边的值比其父节点的key大,则不是二叉排序树,返回0,如果父节点的key大于右边的key,则返回0
			return 0;
		predt = bt->key;				//依次得到key值,注意这个语句的位置,pre的得到是按照左到右的顺序
		printf("\npredt = %d",predt);
		b2 = JudgeBST(bt->rchild);		//判断右边
		return b2;
	}
}
/*
	总结:我觉得数据结构,最重要的是它的思想,真的是非常的精妙。
    像《树》这章,树的层次结构首先我们要清晰,然后就是深刻理解递归的思想,这又牵扯到栈的知识。	 
	 
*/
void main()
{
	BSTNode *bt;
	KeyType k = 6;					//后面要寻找带这个关键字的节点
	int n = 10;						//数组元素个数
	int a[] = {4,9,0,1,8,6,3,5,2,7};	 
	printf("create a BST Tree:\n");
	bt = CreatBST(a,n);				
	printf("BST:\n");
	DispBST(bt);
	printf("\n");
	printf("bt%s\n",(JudgeBST(bt)?"yes,it is a bst":"no,it is not a bst"));
	printf("\n");
	printf("\nsearch the keyword(di gui) : %d",k);
	SearchBST1(bt,k,path, -1);
	printf("\nsearch the keyword(not di gui) : %d",k);
	printf("\ndelete...");
	printf("\nthe origin BST:");
	DispBST(bt);
	printf("\n delete the node 4..");
	DeleteBST(bt,4);
	DispBST(bt);
	printf("\n delete the node 5..");
	DeleteBST(bt,5);
	DispBST(bt);
	printf("\n");
}



  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值