顺序查找 折半查找 分块查找

查找

动态查找:查找的同时对表做修改工作
静态查找:查找的同时不涉及表的修改操作
内查找:在内存中查找
外查找:需访问外存

ASL -- 平均查找长度
ASL成功 -- 成功查找到查找表中元素平均需要的关键字比较次数
ASL失败 -- 没有查找到查找表中元素平均需要的关键字比较次数
ASL是衡量查找算法性能好坏的指标,ASL越大,时间性能越差

从表的一端开始,顺序扫描线性表,依次将扫描到的关键字和给定值k相比较:

一、顺序查找

两种情况的ASL

   ASL不成功=n

顺序查找
int SeqSearch(RecType R[], int n, KeyType k)
{
	int i = 0;
	while (i < n && R[i].key != k)//从表头往后找
	{
		i++;
	}
	if (i >= n)
		return 0;	//未找到返回
	else
		return i + 1;//找到返回逻辑序号+1
}

哨兵
        可以在R 的末尾增加一个关键字为k的元素,称之为哨兵。 增加哨兵后查找过程不再需要判断i是否超界,从而提高查找速度。 带哨兵的顺序查找算法如下:


//改进算法 -- 哨兵
int SeqSearch(RecType R[], int n, KeyType k)
{
	int i = 0;
	R[n].key = k;
	while (R[i].key!=k)
		i++;
	if (i == n)
		return 0;
	else
		return i + 1;

}

二、折半查找

折半查找


折半查找也称为二分查找,要求线性表中的元素必须己按关键字值有序(递增或递减)排列。

int BinSearch(RecType R[], int n, KeyType k)
{
	int low = 0, high = n - 1, mid;
	while (low <= high)		     //当前区间存在元素时循环
	{
		mid = (low + high) / 2;
		if (k == R[mid].key)	     //查找成功返回其逻辑序号mid+1
			return mid + 1;
		if (k < R[mid].key)	              //继续在R[low..mid-1]中查找
			high = mid - 1;
		else
			low = mid + 1;		     //继续在R[mid+1..high]中查找
}
	return 0;
}

判定树

当前查找区间的中间位置上的元素作为根;
左子表和右子表中的元素分别作为根的左子树和右子树。
这样的二叉树称为判定树或比较树。

外部结点

外部结点即查找失败对应的结点,是虚拟的
n个关键字:内部结点为n个,外部结点为n + 1个

                                               

 ASL的两种情况

1.成功二分查找
//恰好是走了一条从判定树的根到被查元素的路径,经历比较的关键字次数恰为该元素在树中的层次。 

2.失败二分查找
//比较过程经历了一条从判定树根到某个外部结点的路径,所需的关键字比较次数是该路径上内部结点的总数,即该外部结点的层次减1。

折半查找改进

假设递增有序顺序表为R[0..n - 1],其中可能存在多个相同关键字的元素,现在求第一个大于等于k的元素位置(从0开始的下标),如果k大于R中全部元素,则返回结果n。
例如,n = 7,R[0..6] = { 1,2,4,4,4,5,6 },k = 2时返回1,k = 4时返回2,k = 10时返回7。
采用基本折半查找算法,对于上述R,当k = 4时返回3,显然是错误的。

int BinSearch2(RecType R[], int n, KeyType k)
{
	int low = 0, high = n - 1, mid;
	while (low <= high)			//查找区间有一个或者更多元素时
	{
		mid = (low + high) / 2;
		if (k <= R[mid].key)
			high = mid - 1;			//继续在左区间查找
		else
			low = mid + 1;			//继续在右区间查找
	}
	return high + 1;
}

三、索引存储结构和分块查找

索引存储结构 = 主数据表 + 索引表      

索引表中的每一项称为索引项,索引项的一般形式是:(关键字,地址) 关键字唯一标识一个元素,地址作为指向该关键字对应元素的指针,也可以是相对地址。

typedef struct 
{  KeyType key;  //KeyType为关键字类型
   int link;	  //指向对应块的起始下标
} IdxType;	  //索引表元素类型

int IdxSearch(IdxType I[],int b,RecType R[],int n,KeyType k) 
{  int s=(n+b-1)/b;		//s为每块的元素个数,即s=n/b
   int low=0,high=b-1,mid,i;
   while (low<=high)	 	//折半查找,找到的位置为high+1
   {  mid=(low+high)/2;
      if (I[mid].key>=k)
         high=mid-1;
      else 
         low=mid+1;
   }
   //在主数据表的high+1块中进行顺序查找
   i=I[high+1].link;
   while (i<=I[high+1].link+s-1 && R[i].key!=k)
      i++;
   if (i<=I[high+1].link+s-1)
      return i+1;		//查找成功,返回该元素的逻辑序号
   else
      return 0;		//查找失败,返回0
}

若以折半查找来确定元素所在的块,则成功时的平均查找长度为:

 若以顺序查找来确定元素所在的块,则成功时的平均查找长度为:

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值