查找、二叉排序树

顺序查找

顺序查找又叫线性查找,是最基本的查找技术,它的查找过程是:从表中第一个记录开始,逐个进行记录的关键字和给定值比较,若某个记录的关键字和给定值相等,则查找成功,找到所查的记录;如果知道最后一个记录,其关键字和给定值比较都不等时,则表中没有所查的记录,查找不成功。

顺序查找算法实现代码如下:

/*顺序查找,a为数组,n为要查找的数组个数,key为要查找的关键字*/
int Sequential_Search(int *a,int n,int key)
{
	int i;
	for(i=1;i<=n;i++)
	{
		if(a[i] == key)
			return i;
	}
	return 0;
}
代码很简单,就是在数组a中查看有没有关键字(key),当你需要查找复杂表结构的记录时,只需要把数组a与关键字key定义成你需要的表结构和数据类型即可。

这里并不够完美,因为每次循环时都需要对i是否越界做判断,事实上,还可以有更好一点的办法,设置一个哨兵,可以解决不需要每次让i与n做判断,实现代码如下:

int Sequential_Search(int *a,int n,int key)
{
	int i;
	a[0] = key;/*设置a[0]为关键字值,我们称之为‘哨兵’*/
	i = n;  /*循环从尾部开始*/
	while(a[i] != key)
	{
		i--;
	}
	return i;
}
此时代码是从尾部开始查找,由于a[0]=key,也就是说,如果a[i]中有key则返回i,查找成功。否则一定在最终的a[0]处等于key,此时返回0,即说明a[1]~a[n]中没有关键字key,查找失败。

折半查找

折半查找(Binary Search)技术,又称为二分查找。它的前提线性表中的记录必须是关键码有序,线性表必须采用顺序存储。折半查找的基本思想是:在有序表中,取中间记录作为比较对象,若给定值与中间记录的关键字相等,则查找成功;若给定值小于中间记录的关键字,则在中间记录的左半区继续查找;若给定值大于中间记录的关键字,则在中间记录的右半区继续查找,不断重复上面过程,知道查找成功,或所有查找区域无记录,查找失败为止。实现代码如下:

int Sequential_Search(int *a,int n,int key)
{
	int low,high,mid;
	low = 1;
	high = n;
	while(low <=high)
	{
		mid = (low+high)/2;
		if(key < a[mid])
			high = mid - 1;
		else if(key >a[mid])
			low = mid + 1;
		else
			return mid;
	}
	return 0;
}

二叉排序树(Binary Sort Tree),又称为二叉查找树,它或者是一颗空树,或者具有下列性质的二叉树。

若它的左子树不为空,则左子树所有结点的值均小于它的根结点的值。

若它的右子树不为空,则右子树上所有结点的值均不大于根结点的值。

它的左,右子树也分别为二叉树。

二叉树的结构:

typedef struct BiTNode
{
	int data;
	struct BiTNode *lchild, *rchild;
} BiTNode , *BiTree;
二叉排序树的查找实现过程代码如下:

/**递归查找二叉树T中是否存在key,
指针f指向T的双亲,其初始调用值为NULL
若查找成功,则指针p指向数据元素结点,并返回TRUE,
否则指针p指向查找路径上访问的最后一个结点并返回FALSE
*/
Status SearchBST(BiTree T ,int key, BiTree f, BiTree *p)
{
	if(!T)
	{
		*p = f;
		return FALSE;
	}
	else if(key == T->data)
	{
		*p = T;
		return TRUE;
	}
	else if(key < T->data)
		return SearchBST(T->lchild,key,T,p);
	else	return SearchBST(T->rchild,key,T,p);
}
二叉排序树的插入操作

代码如下:

/**当二叉排序树T中不存在关键字等于key的数据元素时,
插入key并返回TRUE,否则返回FALSE
*/
Status InsertBST(BiTree *T,int key)
{
	BiTree p,s;
	if(!SearchBST(*T,key,NULL,&p))
	{
		s = (BiTree)malloc(sizeof(BiTNode));
		s->data = key;
		s->lchild = s->rchild = NULL;
		if(!p)
		{
			*T = s;
		}
		else if(key < p->data)
			p->lchild = s;
		else
			p->rchild = s;
		return TRUE;
	}
	else
		return FALSE;
}
二叉树的删除操作:

对二叉树结点的删除分三种情况:

叶子结点

仅有左或右子树

左右子树都有的结点。

我们来看代码,下面这个算法是递归方式对二叉树排序树T查找key,查找到并删除代码:

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

Status Delete(BiTree *p)
{
	BiTree q,p;
	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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值