数据结构之二叉排序树的基本操作

前言

二叉排序树,又称为二叉查找树,它具有以下特点:
若它的左子树不空,则左子树所有结点值均小于它的根结点的值
若它的右子树不空,则右子树所有结点值均大于它的根结点的值
它的左,右子树也分别为二叉排序树
可以为空
前提是二叉树,然后也采用了递归的定义方法

二叉排序树中序遍历就一有序表

构造一颗二叉树,就是把一无序的顺序表变为有序的数集,中序遍历二叉排序表就是一有序的表,其目的,并不是为了排序,而是为了提高查找和删除关键字的速度。

1.关键字

二叉排序树的结构体定义和二叉树的结构体定义完全一样
我们存储的数据都是关键字,说白了就是编号,查找的时候也是,因此在本篇中关键字是唯一的,不能出现两个相同的关键字。

2.二叉排序树的查找操作

查找函数,我们定义为一个可递归运行的函数,函数调用时的语句为:SearchBT(T,key,f,p);参数T为一个二叉链表,key为查找的关键字,f为指向T的双亲,p为了得到查找到的结点位置。
代码如下:

Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
	if(!T)//查找不成功
	{
		*p = f;
		return FALSE;
	}
	else if(key == T->data)//查找成功
	{
		*p = T;
		return TRUE;
	}
	else if(key < T->data)
	{
		return SearchBT(T->lchild,key,T,p);
	}
	else
		return SearchBT(T->rchild,key,T,p);
}

2.二叉排序树的插入操作

只有查得不到的时候,才会进行插入操作,并且将关键字放到树中合适的位置。
代码如下:

Status InsertBT(BTree *T,TElemType key)
{
	BTree p,s;
	if(!SearchBT(*T,key,NULL,&p))//查找失败
	{
		s = (BTree)malloc(sizeof(BTNode));
		s->data = key;
		s->lchild = s->rchild = NULL;
		if(!p)
			*T = s;//插入s为新的根结点
		else if(key < p->data)
			p->lchild = s;//插入s为左孩子
		else
			p->rchild = s;//插入s为右孩子
		return TRUE;
	}
	else
		return FALSE;
}

3.二叉排序树的删除操作

删除操作分为三种情况
1.要删除的结点只有左子树,删除后,将他的左子树整个移动到结点位置

2.要删除的结点只有右子树,删除后,将他的右子树整个移动到结点位置

3.要删除的结点既有左子树又有右子树。找到此结点p的有序直接前驱(或直接后驱)s,用s来替换结点p。然后再删除结点s。

代码如下

Status Delete(BTree *p)
{
	BTree q,s;
	if((*p)->rchild == NULL)//右子树空只需连接它的左子树
	{
		q = *p; *p = (*p)->lchild; free(q);
	}
	else if((*p)->lchild == NULL)//左子树空只需连接它的右子树
	{
		q = *p; *p = (*p)->rchild; free(q);
	}
	else//左右子树均不空
	{
		q = *p; s = (*p)->lchild;
		while(s->rchild)//转左,然后向右到尽头
		{
			q = s;s = s->rchild;
		}
		(*p)->data = s->data;
		if(q != *p)
			q->rchild = s->lchild;//重接q的右子树
		else
			q->lchild = s->lchild;//重接q的左子树
		free(s);
	}
	return TRUE;
}

4.总结

二叉排序树其实就是一种把无序的顺序表变为一个有序表,二叉排序树中序遍历就是有序表。
查找利用了类似二分查找的原理

完整代码

以数组
a[10] = {62,88,58,47,35,73,51,99,37,93};
为例:

#include<stdio.h>
#include<stdlib.h>

#define TRUE  1
#define FALSE 0
typedef int Status;
typedef int TElemType;

typedef struct BTNode
{
	TElemType data;
	struct BTNode *lchild,*rchild;
}BTNode,*BTree;

Status SearchBT(BTree T,TElemType key,BTree f,BTree *p);//查找算法
Status InsertBT(BTree *T,TElemType key);//插入算法
Status Delete(BTree *p);//删除数据算法
Status DeleteBT(BTree *T,TElemType key);//删除算法
void InOrderTraverse(BTree T);//中序遍历二叉树

int main()
{
	int i,x,n,m;
	BTree p = NULL;
	BTree T = NULL;
	int a[10] = {62,88,58,47,35,73,51,99,37,93};
	for(i=0;i<10;i++)
	{
		InsertBT(&T,a[i]);
	}

	while(1)
	{
		printf("1.中序遍历 2.删除算法 3.添加算法 4.查找算法\n");
		scanf("%d",&n);
		switch(n)
		{
		case 1:
			printf("中序遍历二叉树\n");
			InOrderTraverse(T);
			printf("\n");
			break;
		case 2:
			printf("输入要删除的数\n");
			scanf("%d",&x);
			m = DeleteBT(&T,x);
			if(m==TRUE)
			{
				InOrderTraverse(T);
				printf("\n");
			}
			else
				printf("删除失败\n");
			break;
		case 3:
			printf("输入要添加的数\n");
			scanf("%d",&x);
			m = InsertBT(&T,x);
			if(m==TRUE)
			{
				InOrderTraverse(T);
				printf("\n");
			}
			else
				printf("添加失败\n");
			break;
		case 4:
			printf("输入要查找的数\n");
			scanf("%d",&x);
			m = SearchBT(T,x,NULL,&p);
			if(m==TRUE)
			{
				printf("查得:%d\n",x);
			}
			else
				printf("查找失败\n");
			break;
		}
	}
}


Status SearchBT(BTree T,TElemType key,BTree f,BTree *p)
{
	if(!T)//查找不成功
	{
		*p = f;
		return FALSE;
	}
	else if(key == T->data)//查找成功
	{
		*p = T;
		return TRUE;
	}
	else if(key < T->data)
	{
		return SearchBT(T->lchild,key,T,p);
	}
	else
		return SearchBT(T->rchild,key,T,p);
}

Status InsertBT(BTree *T,TElemType key)
{
	BTree p,s;
	if(!SearchBT(*T,key,NULL,&p))//查找失败
	{
		s = (BTree)malloc(sizeof(BTNode));
		s->data = key;
		s->lchild = s->rchild = NULL;
		if(!p)
			*T = s;//插入s为新的根结点
		else if(key < p->data)
			p->lchild = s;//插入s为左孩子
		else
			p->rchild = s;//插入s为右孩子
		return TRUE;
	}
	else
		return FALSE;
}

Status Delete(BTree *p)
{
	BTree q,s;
	if((*p)->rchild == NULL)//右子树空只需连接它的左子树
	{
		q = *p; *p = (*p)->lchild; free(q);
	}
	else if((*p)->lchild == NULL)//左子树空只需连接它的右子树
	{
		q = *p; *p = (*p)->rchild; free(q);
	}
	else//左右子树均不空
	{
		q = *p; s = (*p)->lchild;
		while(s->rchild)//转左,然后向右到尽头
		{
			q = s;s = s->rchild;
		}
		(*p)->data = s->data;
		if(q != *p)
			q->rchild = s->lchild;
		else
			q->lchild = s->lchild;
		free(s);
	}
	return TRUE;
}

Status DeleteBT(BTree *T,TElemType key)
{
	if(!*T)//要删除的数不存在
		return FALSE;
	else
	{
		if(key == (*T)->data)
			return Delete(T);
		else if(key < (*T)->data)
			return DeleteBT(&(*T)->lchild,key);
		else
			return DeleteBT(&(*T)->rchild,key);
	}
}

void InOrderTraverse(BTree T)
{
	if(T == NULL)
		return;
	InOrderTraverse(T->lchild);
	printf("%d ",T->data);
	InOrderTraverse(T->rchild);
}

运行结果

运行结果

后记

二叉排序树其实就是为了动态查找而产生的
还记得动态查找是什么吗:
动态查找在查找过程中插入不存在的元素,删除已存在的元素。

今天的内容就是二叉排序树的基本操作及其内容,喜欢我的多多支持哦~

发布了12 篇原创文章 · 获赞 10 · 访问量 1136

猜你喜欢

转载自blog.csdn.net/bsqetuo/article/details/100063313