数据结构之查找

一:查找的基本概念
(1)查找表: 由同一类型的数据元素构成的集合
1)静态查找表:只做查找操作的查找表
1)查询某个“特定数据”元素是否在查找表中。
2)检索某个特定的数据元素和各种属性;
2)动态查找表:在查找过程中同事插入查找表中不存在的数据元素,或者从查找表中删除已经存在的某个数据元素。
1)查找时插入元素
2)查找时删除元素
(2)关键字: 数据元素中某个数据项的值。
  1)主关键字:关键字能唯一的标识一个数据元素(记录)
  2)次关键字: 可以识别多个数据元素的关键字
(3)查找:根据给定的某个值,在查找表中确定一个其关键字等于给定值的数据元素

二:顺序表查找:
(1)顺序表查找算法:时间复杂度为O(n)
/顺序查找,a为数组,n为要查找的数组元素个数,key为要查找的关键字;/

 int Sequential_Serch(int *a, int n, int key)
    		{
    			int i;
    			for(i = 1; i <= n; i++)
    			{
    				if(a[i] == key)
    					return i;
    			}
    			return 0;
    		}

**(2)顺序表查找优化:**时间复杂度为O(n)
/设置哨兵;/

int Sequential_Serch(int a*, int n, int key)
		{
			int i = n;	//循环从数组尾部开始
			a[0] = key;	//设置a[0]为关键字,我么称之为“哨兵”;
			while(a[i] != key)
			{
				i--;
			}
			return i;	//返回0说明查找失败。
		}

三:有序表查找:
(1)折半查找(二分查找):前提是表中的记录必须是关键码有序(通常从小到大):时间复杂度为O(logn);

int Binary_Serch(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;		//若相等,则说明mid即为查找到的位置
			}
			return 0;
	}

**(2)插值查找:**讲折半的公式调整后为: mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low)
时间复杂度仍为O(logn)

int Insert_Serch(int *a, int n; int key)
		{
			int low, high, mid;
			low = 1;	//定义最低下标为记录首位;
			high = n;	//定义最高下标为记录末位
			while(low <= high)
			{
				mid = low + (key - a[low]) / (a[high] - a[low]) * (high - low);		//插值
				if(key < a[mid])		//若查找值比中值小
				{
					high = mid -1;		//最高下标调整到中位下标小一位
				}
				else if(key > a[mid])		//若查找值比中值大
				{
					low = mid + 1;		//最低下标调整到中位下标大一位
				}
				else
					return mid;		//若相等,则说明mid即为查找到的位置
			}
			return 0;
		}

(3)斐波拉契查找:利用黄金分割原理实现。 利用F[k] = F[k-1] + F[k-2]的变形,时间复杂度O(logn)
先需要你一斐波拉契数列的数组
下标 0 1 2 3 4 5 6 7 8 9 10
F 0 1 1 2 3 5 8 13 21 34 …

int Fibonacci_Serch(int *a, int n, int key)
		{
			int low, high, mid;
			int i, k;
			low = 1;	//定义最低下标为记录首位;
			high = n;	//定义最高下标为记录末位
			k = 0;
			while(n > F[k]-1)	//计算n位于斐波拉契数列的位置
				k++;
			for(i = n; i < F[k]-1; i++)	//将不满的数值补全
			{
				a[i] = a[n];
			}
			
			while(low <= high)
			{
				mid = low + F[k-1] - 1;		//计算当前分隔的下标
				if(key < mid)
				{
					high = mid - 1;
					k = k -1;		//斐波拉契数列下标减一位
				}
				else if(key > mid)
				{
					low = mid + 1;
					k = k-2;		//斐波拉契数列下标减两位
				}
				else
				{
					if(mid <= n)
						return mid;	//若想等,说明mid为查找到为位置
					else
						return n;	//若mid>n,说明为补全数据,返回n
				}
			}
			return 0;
		}

这里之所以是F[K]-1而不是F[k],是因为F[k]-1 = F[k-1]-1 + F[k-2]-1 + 1;加1加的是mid那个位置)
而F[k] != F[k-1] + F[k-2] + 1
  从low到high一共是F[k]-1个数据,减一是要去掉mid
|low |mid| high|
↖F[k-1] -1↗ ↖ F[k-2]-1↗

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值