数据结构-查找(顺序查找,加监视稍,折半查找(代码实现),分块查找 散链表(哈希表)查找(无代码))

查找算法

数据结构-查找(顺序查找,加监视稍,折半查找(代码实现),分块查找,散链表查找(无代码))
一,顺序查找1
按照线性顺序,一个一个的比较,找到返回其位置,找不到返回值0

int Seq_Search1(SeqList p,DataType a)
{
	int i=1;
	while(i<=p.length&&p.data[i]!=a)
	{
		i++;
	}
	if(i>p.length)
		return 0;
	else 
		return i;
}

二,顺序查找2(加监视稍)

int Seq_Search2(SeqList p,DataType a)
{
	int i;
	p.data[0]=a;//监视稍
	i=p.length;
	while(p.data[i]!=a)
	{
		i--;
	}
	return i;
}

比较次数少,效率更高!!!

顺序表上的顺序查找性能分析

对于n个元素的查找表,若查找的是第i个记录时,需进行n-i+1次关键字比较,即ci=n-i+1。设查找每个元素的概率相等。
查找成功时,顺序查找的平均查找长度为:
在这里插入图片描述

查找不成功时,表中每个关键字都要比较一次,直到监视哨,因此关键字的比较次数总是n+1次

在这里插入图片描述

二,折半查找
折半查找的思想为:在有序表中,取中间元素作为比较对象,
若给定值与中间元素的关键字相等,则查找成功;若给定值小
于中间元素的关键字,则在中间元素的左半区继续查找;若给
定值大于中间元素的关键字,则在中间元素的右半区继续查找。
不断重复上述查找过程,直到查找成功,或所查找的区域无数
据元素,查找失败。

例如: key=64 的查找过程如下:
在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
伪代码
key≠data[mid],key>p.data[mid]
∴low=mid+1
mid=(low+high)/2
在这里插入图片描述
a≠data[mid],key<data[mid]
∴high=mid-1
mid=(low+high)/2
在这里插入图片描述
a=data[mid] 此时就找到了key(关键字)
返回 mid 下标值

int Binary_Search(SeqList p,DataType a)
{
    int mid,low=1,high=p.length;
	while(low<=high)
	{
		mid=(low+high)/2;
		if(a==p.data[mid])
		{return mid;}
		else if(a<p.data[mid])
		{high=mid-1;}
		else
			low=mid+1;
		return 0;
	}
}

在这里插入图片描述折半查找的平均查找长度可用判定树来分析

设 i=11
在这里插入图片描述
先判断根节点

当判定树的左子树
即将查找区间调整到左半区,此时的查找区间是

[1,5],也就是说,左分支上为根结点的值减1,代表查找区间的高端high,此时,根结点的左孩子是(1+5)/2=3,

当判定树的右子树
即将查找区间调整到右半区,此时的查找区间是

[7,11],也就是说,右分支上为根结点的值加1,代表查找区间的低端low,此时,根结点的右孩子是(7+11)/2=9

重复,依次确定每个结点的左右孩子
在这里插入图片描述
在这里插入图片描述
关于平均查找长度,应用到树形结构的知识,可以点击这里:
树与二叉树链接地址

三 分块查找(索引顺序查找)
1,首先把一个大的线性表分解成若干块,线性表有序或者分块有序,分块必须有序,(若i<j,则第j块中所有记录的关键字均大于第i块中的最大关键字);
2,建立“索引表”(每个结点含有最大关键字域和本块第一个节点的指针,且按关键字有序,如下图所示)

查找过程 先确定待查记录所在快(顺序或折半查找)再在块内查找。

索引储存表示
在这里插入图片描述
设分块查找中将长为 n 的表分成均等的 m个块,每块 s 个元素,则 m = (n / s)上取整,
索引顺序表=索引+顺序表
一般情况下,索引表为有续表
查找步骤:
1.由索引表确定所在区间;
2.在顺序表的某个区间进行顺序查找,也可折半查找。

如果索引表中采用顺序查找,则

ASL=ASL(索引)+ASL(顺序表)

ASL=(m+1)/2+(s+1)/2

如果索引表中采用折半查找,则

ASL=(s+1)/2+log2(m+1)-1

对于表长n确定的情况下,m=

在这里插入图片描述

此时分块查找的ASL达到最小值!!! 考点!!考点!!!

上述三种方法的比较
折半查找具有最高的查找效率,但要求必须是顺序存储结构且元素有序排列,且若要进行插入,删除运算时,因需移动大量元素,运行效率降低,所以折半查找只适用于有序表静态查找;
顺序查找效率最低,但对线性表无任何要求(顺序存储或链式存储都可),是否有序都不影响。
分块查找是顺序查找折半查找的综合。

四,散列表查找*

散列查找不同与上述查找
散列表也叫哈希(hash)表或杂凑表,是基于散列存储策略建立的查找表。
基本思想是确定一个函数,求得每个关键字相应的函数值并以此作为存储地址,直接将该数据元素存入到相应的地址空间去,因此它的查找效率很高
但是哈希函数经常产生冲突,一般情况下只能选择适当的哈希函数,使冲突尽可能的减少。

(1)构造好的散列函数Hash(key)。
好的散列函数应符合以下两个原则:
① 所选函数尽可能简单,以便提高转 换速度;
② 所选函数对关键字计算出的地址, 应在散列地址集中大致均匀分布,以 减少空间浪费。
(2) 制定解决冲突的方案。

常用的散列函数

实际造表时,采用何种构造哈希函数的方法取决于建表的关键字集合的情况(包括关键字的范围和形态),总的原则是使产生冲突的可能性降到尽可能地小。
在这里插入图片描述
p一般选取为小于m的最大的质数,也可以是不包含小于20质因子的合数。

将包含11个元素的关键字序列{ 18,27,1,20,22,6,10,13,41,15,25}。存储在一个长度为12的连续存储空间。
选取关键字与元素位置间的函数为 f(key)=key%11
18%11=7 a[7]=18,27%11=5 a[5]=27 … …
则存储情况为
在这里插入图片描述
若要存储23, 23%11=2 a[2]=23,与上表产生冲突
那么怎么解决冲突呢?

处理冲突的方法及散列表的构造和查找

1,开放地址法
用开放定址法处理冲突就是当冲突发生时,形成一个地址序列。沿着这个序列逐个探测,直到找出一个“空”的开放地址,将发生冲突的关键字值存放到该地址中。
在这里插入图片描述
其中m为哈希表长, di为增量函数。
增量序列的取法不同,可得到不同的开放地址处理冲突探测方法。

(1)线性探测
Hi=(Hash(k)+di) % m
其中:di=1,2,……,m-1

关键字集合
{19,01,23,14,55,68,11,82,36}
设定哈希函数H(k)=k MOD 11(表长=11)
若采用线性探测再散列处理冲突
19%11=8 a[8]=19,
01%11=1 a[1]=01,
23%11=1 a[1]=11,
此时产生冲突
(23+1)%11=2 a[2]=23 解决冲突
14%11=3 a[3]=14,
55%11=0 a[0]=55,
在这里插入图片描述
68%11=2 a[2]=68 产生新的冲突
继续向后探测 (68+1)%11=3 a[3]=68 产生新的冲突
继续探测 (68+1+1)%11=4 a[4]=68 冲突解决!
在这里插入图片描述
继续
11%11=0 a[0]=11 又产生冲突
向后探测 (11+1)%11=1,(11+2)%11=2,(11+3)%11=3,(11+4)%11=4,(11+5)%=5 冲突解决!
在这里插入图片描述
继续
82%11=5 产生冲突
(82+1)%11=6 a[6]=82 解决冲突!
继续
36%11=3 产生冲突
(36+1)%11=4,(36+2)%11=5,(36+3)%11=6,(36+4)%11=7 a[7]=36 解决冲突!
在这里插入图片描述
求 ALS 平均查找长度

先在序列下方标上每个空间要查找的次数:
在这里插入图片描述
ALS=1/9×(1×4+2×2+3+5+6)=22/9

2)二次探测法(平方探测法)
Hi=(Hash(k)+di+m) % m
di=1^2.
-1^2,
2^2,
-2^2,

k^2,
-k^2 (k<=m/2)

还是上述的关键字集合
{19,01,23,14,55,68,11,82,36}
设定哈希函数H(k)=k MOD 11(表长=11)
若采用二次探测再散列处理冲突
19%11=8 a[8]=19,
01%11=1 a[1]=01,
23%11=1 a[1]=11,此时产生冲突
(23-1^2)%11=2 a[2]=23
14%11=3 a[3]=14,
55%11=0 a[0]=55,
在这里插入图片描述
68%11=2 a[2]=68 此时产生冲突
开始二次探测 (68+1^2)%11=3,有新的冲突
(68-1^2)%11=2,又有新的冲突
(68+2^2)% =6,a[6]=68,解决冲突!

继续探测 11%11=0 产生冲突
(11+1^2)%11=1 有新的冲突
(11-1^2)%11=-1(10) 循环到序列尾部 解决冲突!
在这里插入图片描述
继续探测 82%11=5 a[5]=82,
36%11=3,产生冲突
(36+1^2)%11=4,解决冲突!
在这里插入图片描述
求ALS
ALS=(1×5+2×2+3+4)/9=16/9

3)双散列函数探测法*

2,拉链法(链地址法)
在这里插入图片描述
根据哈希函数将所有哈希地址相同的记录都链接在同一链表中,如下图
在这里插入图片描述
ALS=(6×1+2×2+3)/9=13/9
散列表查找性能分析
散列表的查找过程与建表过程一致。
从查找过程得知,哈希表查找的平均查找长度实际上并不等于1。
决定哈希表查找的ASL的因素:
1)选用的哈希函数;
2)选用的处理冲突的方法;
3)哈希表饱和的程度
——装填因子α=n/m的大小
(n—表中填入的记录数,m—哈希表的长度

3,公共溢出法
为所有冲突的关键字开辟一个公共的溢出区来存放,适用于相对于基本表来说冲突数据很少的情况

欢迎指错!!!

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值