数据结构 查找

基于线性表的查找

线性表查找

顺序查找:

从左到右便利整个表,依次查找对应的值,如果某个值与给定要查找的给定值相等。则查找成功。否则查找失败。
数据元素类型定义:

typedef struct{
	KeyType key;        // 关键字域
	InfoType otherinfo; // 其他域
}ElemType;

顺序表定义

typedef struct{
	ElemType *R;    // 存储空间基地址
	int length;     // 当前长度
}SSTable;
实现:
顺序查找:
int Search_Seq(SSTable ST , KeyType key){
// 从左往右遍历,若查找成功到则返回该元素的地址,查找失败则返回 0;
	// 从高地址向低地址查找
	for(i = ST.length; i>=1; --i){
		if(ST.R[i].key == key)return i;
		return 0;
	}
}
设置哨岗的顺序查找:
int Search_Seq(SSTable ST,KeyType key){
	ST.R[0].key == key;// 设置监视哨岗
	for(i = ST.length ; ST.R[i].key != key ; --i)//  向后查找
	return i;
}

算法分析:
平均搜索长度(ASL):
在这里插入图片描述
n : 记录的个数
pi :查找第 i 个记录的概率 ( 通常认为pi =1/n )
ci :找到第 i 个记录所需要的比较次数

ASL = (n+1)/2

优点:

简单,对表的结构无任何要求,即适合顺序结构,也适合链式结构,无论是否有序都可以使用,

缺点:

ASL 较大,查找效率较低,当n很大的时,不适宜使用。

折半查找(二分查找法):

使用限制;

要求线性表必须采用顺序存储结构,而且表中元素按关键字有序排列。

实现:

实现步骤:

  1. 设置查找区间 low 和 high
  2. 在 low <= high 的条件下(防止越界)
  3. 取 low 和 high 的中间值 mid
  4. 将给定值 key 与 mid 进行比较查找成功则返回 mid
  5. 否则比 mid 小则向前查找,比 mid 大则向后查找。
  6. 查找失败则返回 0
int Search_Bin(SSTable ST , KeyType key){
	low = 1 , high = ST.length;
	while (low <= high){        // 执行循环的条件
		mid = (low + high)/2;
		if(key == ST.R[i].key)return mid; // 找到返回该地址
		else if(key < ST.R[mid].key) high = mid - 1; // 如果比该值小的话,向前查找  
		else low = mid + 1;// 如果比该值大则向后查找 
	}
	return 0; // 查找失败
}

二分查找可以用二叉树来表示(又叫决策树)

决策树表示:

题目:
已知 (5,16,20,27,30,36,44,55,60,67,71)查找关键字27.
在这里插入图片描述
决策树表示:
在这里插入图片描述
每个结点都是(low + high) / 2得到的,通过 mid 来划分区域,而结点下面的分支是下一个访问的地址下标。

ASL 平均查找长度为:log2(n+1)-1
因此 时间复杂度为:O(log2n)。

基于树表的查找

二叉排序树

又叫二叉查找树。

定义:

二叉排序树 或者 是一棵空树,或者具有列性质的二叉树
(1)若它的左子树,不为空则左子树上的所有结点值均小于它的根结点的值;
(2)若它的右子树,不为空则右子树上的所有结点值均大于它的根节点的值;
(3)它的左,右子树也分别叫做二叉排序树。
在这里插入图片描述

二叉排序树的画法:

(口诀)第一个数作为根节点,剩下的数,小的放左,大的放右。

分析

二叉排序树查找算法的性能取决于二叉树的结构,而二叉树的形状则取决于其数据集。如果数据是有序排列则查找时间为O(n);反之如果二叉排序树的结构合理,则查找速度较快,时间复杂度为O(log2n)(树的高度越小,查找速度越快)
为了使二叉树的高度尽量的小,我们引入一种特殊的二叉树。

平衡二叉树(AVL)

定义:

具有以下特征的树称为平衡二叉树,

(1) 左子树和右子树深度之差的绝对值不超过 1(2) 左子树和右子树也是平衡二叉树。
平衡因子(BF)
定义:

该结点左子树和右子树的深度差。(则平衡二叉树的平衡因子只可能为1,0,-1,如果平衡二叉树有一个结点平衡因子绝对值大于1,则该二叉树就不平衡)。
在这里插入图片描述
结点上的数字表示 左右结点之间的差值(计算方式:左子树高度- 右子树高度)。

最小不平衡子树

距离 插入结点(就是根结点)最近的,且 BF(平衡因子)的绝对值大于 1 的结点为根结点的子树。

说到这,那么我们要怎么将二叉树调整为平衡二叉树呢?

平衡二叉树的调整方法

在这里插入图片描述
左边这个二叉树右子树大于左子树我们要将他们转换为平衡二叉树,将多的一边三个中选择三个数之间的中间值,放到中间,其余按照,小的放在左边,大的放在右边排序就可以了。

基于散列表的查找

散列表概念:

根据给定的关键字来计算出关键字在表中的地址的数据结构。也就是说散列表建立了关键字 和 存储地址之间的一种直接映射关系。

散列函数和散列地址

在记录的存储位置 p 和其关键字 key 之间建立一个确定的对应关系 H ,
使 p = H(key)称这个对应关系 H为散列函数,p 为散列地址。

散列函数的构造方法

构造散列函数通常考虑:

	1.散列表长度
	2.关键字长度
	3.关键字的分布情况
	4.计算散列函数所需要的时间
	5.记录好查找频率

一个好的散列表满足两个原则:
(1)函数简单好计算,每一个关键字只有一个散列地址与之对应;
(2)函数的值域需在表长范围内,计算出的散列地址分布应均匀,尽量少冲突。

构造方法有:数字分析法,平方取中法,折叠法和除留余数法;
我们就讲下除留余数法:
假设散列表的表长为 m ,选择一个不大于 m 的数 p ,用 p 去除关键字,除后得到余数为散列地址;
例如:
在这里插入图片描述
对每个 key 值都对 7 取余得到地址,如果发生冲突则向后移动一位,比较次数加一。得到下表:
在这里插入图片描述
平均查找长度:
ASLsucc=(1+1+1+2+3+4+1+2)/ 8=15/8
(所有成功的次数加起来的和 / 成功的 key 值数 )
(例如这里成功的 key 有 8 个,地址从 0 到 7 都有对应值 所以为8)

处理冲突的方法

(1)线性探测法

发生冲突就向下一个单元顺序寻找空单元

(2)二次探测法
在这里插入图片描述

每次冲突就按照,上图的顺序为每次的步长进行寻找空单元,
第一次向 右 步长为1,第二次向 左 步长为1,
第三次向 右 步长为4,第四次向 左 步长为4,依次递推……

(3)伪随机数探测法
就是取关键字的一个随机函数值作为它的哈希地址,适用于关键字长度不一的情况

参考:
《数据结构 c 语言版 第二版》严蔚敏
【数据结构与算法】初入数据结构的哈希表(Hash Table)

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值