Loading

二叉搜索树

二叉搜索树是为了解决动态查找问题而提出来的,也叫做二叉排序树或二叉查找树。

基本概念

二叉搜索树(BST, Binary Search Tree):一棵二叉树,可以为空;如果不为空,则要满足以下性质:

非空左子树的所有键值小于其根结点的键值
非空右子树的所有键值大于其根结点的键值
左、右子树都是二叉搜索树
对二叉搜索树进行中序遍历,即可得到有序的数列

抽象数据类型描述

类型名称:二叉搜索树
数据对象集:一棵二叉树,对于树中每个结点X,它的左子树中所有关键字值小于X的关键字值,而它的右子树中所有关键字值大于X的关键字值
操作集:BST是SearchTree类型,X是ElementType类型

  • Position Find(SearchTree BST, ElementType X):从二叉搜索树BST中查找元素X,返回其所在结点的位置
  • Position FindMin(SearchTree BST):从二叉搜索树BST中查找并返回最小元素所在结点的位置
  • Position FindMax(SearchTree BST):从二叉搜索树BST中查找并返回最大元素所在结点的位置
  • SearchTree Insert(SearchTree BST, ElementType X):把元素X插入到二叉搜索树BST中
  • SearchTree Delete(SearchTree BST, ElementType X):把元素X从二叉搜索树BST中删除

查找操作

递归形式

Position Find(SearchTree BST, ElementType X){
	if(BST=NULL)
		return NULL;
	if(X<BST->Data)
		return Find(BST->Left,X);		//尾递归
	else if(X>BST->Data)
		return Find(BST->Right,X);
	else
		return BST;
}

迭代形式,执行效率较高

Position Find(SearchTree BST, ElementType X){
	while(BST){
		if(X>BST->Data)
			BST=BST->Right;
		else if(X<BST->Data)
			BST=BST->Left;
		else
			return BST;
	}
	return NULL;
}

查找最大最小元素

最大元素一定在树的最右分支的端结点上,而最小元素一定在树的最左分支的端结点上。
递归实现

Position FindMin(SearchTree BST){
	if(!BST)
		return NULL;
	else if(BST->Left==NULL)
		return BST;
	else
		return FindMin(BST->Left);
}


Position FindMax(SearchTree BST){
	if(!BST)
		return NULL;
	else if(BST->Right==NULL)
		return BST;
	else
		return FindMax(BST->Right);
}

迭代实现

Position FindMin(SearchTree BST){
	if(BST)
		while(BST->Left!=NULL)
			BST=BST->Left;
	return BST;
}


Position FindMax(SearchTree BST){
	if(BST)
		while(BST->Right!=NULL)
			BST=BST->Right;
	return BST;
}

插入

二叉搜索树的插入操作,可以采用与Find类似的方法,确定插入位置

SearchTree Insert(SearchTree BST, ElementType X){
	if(BST==NULL){		//原树为空,则先创建一棵树,生成一个结点
		BST=(SearchTree)malloc(sizeof(struct TNode));
		BST->Data=X;
		BST-Left=BST->Right=NULL;
	}
	else{
		if(X<BST->Data)
			BST->Left=Insert(BST->Left,X); 		  //递归插入左子树
		else if(X>BST->Data)
			BST->Right=Insert(BST->Right,X);		//递归插入右子树
		//else X在树中已存在,则什么都不做
	}
	return BST;
}

删除

删除一个元素,要考虑三种情况:

  1. 要删除的是叶结点:直接删除,再修改其父结点指针,置为NULL
  2. 要删除的结点只有一个孩子结点:将其父结点的指针指向要删除的孩子结点
  3. 要删除的结点有左、右两颗子树:用右子树的最小元素或者左子树的最大元素替代被删除结点
SearchTree Delete(SearchTree BST, ElementType X){
	Position tmp;
	if(BST==NULL)
		printf("要删除的元素未找到\n");
	else{
		if(X<BST->Data)
			BST->Left=Delete(BST->Left,X);		//从左子树递归删除
		else if(X>BST->Data)
			BST->Right=Delete(BST->Right,X);		//从右子树递归删除
		else{		//找到了要被删除元素的位置
			if(BST->Left&&BST->Right){		//被删除结点有两个子节点
				tmp=FindMin(BST->Right);		//找到右子树的最小元素
				BST->Data=tmp->Data;		//替代被删除结点
				BST->Right=Delete(BST->Right,BST->Data);	//删除右子树的最小元素
			}
			else{		//被删除结点有一个或零个子结点
				tmp=BST;
				if(BST->Left==NULL)		//只有右孩子或无子结点
					BST=BST->Right;
				else		//只有左孩子
					BST=BST->Left;
				free(tmp);
			}
		}
	}
	return BST;
}
posted @ 2020-07-05 18:51  Kinopio  阅读(206)  评论(0编辑  收藏  举报