看数据结构写代码(53) 静态查找表(线性查找,二分查找,斐波那契查找,插值查找)

查找定义 :根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素(或记录)。
查找表分类:静态查找表和动态查找表。
静态查找表:只查找,而不进行插入,删除。
动态查找表:在查找过程中同时插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。

静态表的 查找 大致 四种 算法: 线性查找,二分查找,斐波那契查找和插值查找。 其中 在线性查找之前,对表 无要求。对于 其余三种 需要 在查找之前 排序。插值查找 除了 需要 排序,还需要 均匀分布。

下面 给出代码:
线性查找:平均查找长度ASL = (n+1)/2
//无序表,顺序查找
int line_Search(int * array,int len,int key){
	for (int i = 0; i < len; i++){
		if (array[i] == key){
			return i;
		}
	}
	return -1;
}
线性 查找 ,可以 在 第一个位置 ,或者 最后一个位置 放一个 “哨兵”,其值等于 key。这样 可以防止 查找出界,并且效率提高很多。
int Sequential_Search2(int *a, int n, int key)
{
     int i;
     a[0] = key;
     for(i = n; a[i] != a[0]; i--);
     return i;
}

二分查找:又叫折半查找,算法简单,效率高,,ASL = (log以2为底的n+1 ) -1 
//二分查找,查找之前需要排序
int search_Bin(int * array,int len,int key){
	int low = 0;
	int high = len -1;
	while (low <= high){
		int mid = (low + high) /2 ;
		if (array[mid] == key){
			return mid;
		}
		else if( array[mid] > key){
			high = mid - 1;
		}
		else{
			low = mid + 1;
		}
	}
	return -1;
}

斐波那契查找:效率高,空间复杂度高,易出错(数组越界)
//斐波那契查找
#define MAX_SIZE 30
void fibonacci(int * f){
	f[0] = 0;
	f[1] = 1;
	for (int i = 2; i < MAX_SIZE; i++){
		f[i] = f[i-1] + f[i-2];
	}
}

int fibonacci_Search(int * array,int len,int key){
	int low = 0;
	int high = len -1;
	int f[MAX_SIZE];
	fibonacci(f);//创建斐波那契数列
	int k;
	for (k = 0; k < MAX_SIZE; k++){//寻找最小匹配的斐波那契数
		if (f[k] >= len){
			break;
		}
	}
	for (int i = len; i < f[k]; i++){//补齐不足的位置
		array[i] = array[high];
	}
	while (low <= high){
		int mid = low + f[k-1] -1;//斐波那契查找效率高,因为在计算机里 加法 比 除法简单.
		if (key > array[mid]){
			low = mid + 1;
			k = k-2;
		}
		else if(key < array[mid]){
			high = mid - 1;
			k = k - 1;
		}
		else{
			if (mid <= high){//这一步 不懂
				return mid;
			}
			else{
				return -1;
			}
		}
	}
	return -1;
}
斐波那契查找 不是 每次 查找 表长的 一半,而是 用 某个 斐波那契数 分割 表。 斐波那契比 二分查找 效率高 是因为 二分 查找  在计算 mid时用的是除法:int mid = (low + high) /2 ; 而 斐波那契 用 的是 加法:int mid = low + f[k-1] -1; 但是 斐波那契算法 需要 表长 必须为 某个斐波那契数 -1,所以 需要 表要 留有一些空间。

插值 查找:当我们 在 字典里 查找 “apple”时,我们 并不会从 打开字典的一半进行查找,而是从 前面开始查找。当我们 查找“zero”时,我们从 尾部开始查找。 这就是 插值查找 和 二分查找的区别。他会 根据 key值 在 表里 的 比例 来 安排 查找的 位置;
插值 查找,与二分查找,代码 仅 一句 不同:
int mid = low + (high-low)*((key-array[low])/(array[high]-array[low]));//根二分查找仅此区别
//插值查找
//顺序表+ 均匀分布
int insertValue_Search(int * array,int len,int key){
	int low = 0;
	int high = len -1;
	while (low <= high){
		//根据比例查找
		int mid = low + (high-low)*((key-array[low])/(array[high]-array[low]));//根二分查找仅此区别
		int midValue = array[mid];
		if (midValue > key){
			high = mid -1;
		}
		else if(midValue < key){
			low = mid +1;
		}
		else{
			return mid;
		}
	}
	return -1;
}

总结:
折半查找进行加法与除法运算(mid = (low + high) / 2),插值查找进行复杂的四则运算( mid = low + (key - a[low] / (a[high] - a[low]) * (high - low)) ),斐波那契查找只是运用简单家减法运算 (mid  = low + f[k-1] -1) ,在海量的数据查找过程中,这种席位的差别会影响最终的查找效率。三种有序表的查找本质上是分割点的选择不同,各有优劣,实际开发可根据数据的特点综合考虑再做决定。

完整源代码网盘地址: 点击打开链接







评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值