通过函数理解——分块查找

索引表中折半查找,块内进行顺序查找



#include <stdio.h>
#include <malloc.h>
#define MAXL 100		//最大长度
typedef int KeyType;	//定义关键字类型为int
typedef char InfoType;

typedef struct
{
	KeyType key;		//关键字项
	InfoType data;		//其他数据项,类型为InfoType
} RecType;				//查找元素的类型

void CreateList(RecType R[], KeyType keys[], int n)	//创建顺序表
{
	for (int i = 0; i < n; i++)			//R[0..n-1]存放排序记录
		R[i].key = keys[i];
}
void DispList(RecType R[], int n)	//输出顺序表
{
	for (int i = 0; i < n; i++)
		printf("%d ", R[i].key);
	printf("\n");
}
#define MAXI 20						//定义索引表的最大长度
typedef struct
{
	KeyType key;					//KeyType为关键字的类型
	int link;						//指向分块的起始下标
} IdxType;							//索引表元素类型

int IdxSearch(IdxType I[], int b, RecType R[], int n, int s,KeyType k) //分块查找
{
				//s为每块的元素个数,应为n/b取上界
	int count1 = 0, count2 = 0;
	int low = 0, high = b - 1, mid, i;
	printf("(1)先在索引表中折半查找\n");
	while (low <= high)			//在索引表中进行折半查找,找到的位置为high+1
	{
		mid = (low + high) / 2;
		printf("  第%d次比较:在[%d,%d]中,比较索引表中元素I[%d],即比较元素R[%d]:%d\n", count1 + 1, low, high,mid, mid*s, R[mid*s].key);
		if (I[mid].key >= k)
			high = mid - 1;
		else
			low = mid + 1;
		count1++;				//count1累计在索引表中的比较次数
	}
	printf("\n比较%d次,还需要在索引表中第%d块中查找元素%d\n", count1, low, k);
	//应在索引表的high+1块中,再在主数据表中进行顺序查找
	i = I[high + 1].link;			//找到对应的块
	printf("\n(2)后在索引表的对应块中顺序查找:\n    ");
	while (i <= I[high + 1].link + s - 1)
	{
		printf("  %d ", R[i].key);
		count2++;				//count2累计在顺序表对应块中的比较次数
		if (R[i].key == k) break;
		i++;
	}
	printf("比较%d次,在顺序表中查找元素%d\n", count2, k);
	if (i <= I[high + 1].link + s - 1)
		return i + 1;			//查找成功,返回该元素的逻辑序号
	else
		return 0;			//查找失败,返回0
}

int main()
{   KeyType k = 71;//设置待查找的数
	RecType R[MAXL];
	IdxType I[MAXI]; //前面宏定义#define MAXI 20
	int n = 25, i;
	int a[] = { 8,14,6,9,10,18,22,19,34,31,40,38,54,56,66,68,71,78,80,85,94,88,96,87,100 };
	//需要注意索引表中的前一块的所有元素都要比后一块的所有元素小,观察上面的数组,可得块内元素的个数可为:5,6,但不能为7
	CreateList(R, a, n);				//建立顺序表
	
	int t,j=0,temp;
	
	int s=6;//索引表中块内元素的个数,可以自行设置,但是在设置时,需要注意索引表中的前一块的所有元素都要比后一块的所有元素小,
	int b;//索引表的长度,即索引表中块的个数
	if (n%s)//确定索引表的长度,即索引表中块的个数
		b = n / s + 1;
	else
		b = n / s;
	for (t = 0; t < b; t++)
	{
		temp = a[t*s];
		I[t].link = t * s ;
		for (j= 0; j < s; j++)
		{
			if (temp <= a[t * s + j])
			{
				temp = a[t * s + j];
				I[t].key = temp;
				
			}
			
		}
		

	}
	//I[0].key = 14; I[0].link = 0;		//建立索引表
	//I[1].key = 34; I[1].link = 5;
	//I[2].key = 66; I[2].link = 10;
	//I[3].key = 85; I[3].link = 15;
	//I[4].key = 100; I[4].link = 20;
	printf("关键字序列:");
	for (i = 0; i < n; i++)
	{
		printf("%4d", R[i].key);
		if (((i + 1) % s) == 0) printf("   ");
		if (((i + 1) % (2*s)) == 0) printf("\n\t   ");
	}
	printf("\n");
	
	printf("查找%d的比较过程如下:\n", k);

	if (i=IdxSearch(I, b, R, 25,s, k))
		printf("元素%d的位置是第%d个数\n", k, i);
	else
		printf("元素%d不在表中\n", k);
	return 1;
}


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值