查 找
导图

基本概念
查找: 在数据集合中寻找满足条件的数据元素的过程。结果分为查找成功和查找失败。
查找表: 用于查找的数据集合,由同一种数据类型(或记录)的组成,可以是一个数据或链表等数据类型。
操作: 分为静态查找表和动态查找表
-
静态查找表:
- 查询某个特定数据元素是否在表中。
- 检索满足条件的某个特定的数据元素的各种属性。
-
动态查找表:
- 在查找表中插入一个数据元素。
- 从表中删除一个数据元素。
关键字: 数据元素中唯一标识该元素的某个数据项的值,使用基于关键字的查找 ,查找的结果是唯一的。
平均查找长度: 关键字比较次数的平均值: ASL
顺序查找
顺序查找又称线性查找,主要用于在线性表中进行查找。
算法实现:
// 顺序存储
int Search(int arr[],int n, int key)
{
int i;
for(i=o; i<n; ++i)
{
if(arr[i] == key)
{
return i;
}
}
return -1;
}
// 链式存储
LNode* Search(LNode* head, int key)
{
LNode* p = head -> next;
while(p != NULL)
{
if( p->data == key )
{
return p;
}
p = p->next;
}
return NULL;
}
注意:
ASL = (n为表中数据元素,查找失败则为n)
折半查找
折半查找又称二分查找。
前提:对数据元素进行排序
思想:将待查找元素与中间元素比较,若大于中间元素(按升序排序),则在后半部分继续进行二分查找,以此类推直至找到元素,否则返回无此元素。
代码实现
// len 线性表长度, elem 查找关键字
int binSearch(int list[], int len, int elem)
{
int left, right, mid;
left = 0;
right = len - 1;
while( left <= right )
{
mid = (left + right)/2; //计算中间元素的下标
if( list[mid] == elem )
{
return mid;
}else if( list[mid] > elem )
{
//如果中间元素大于查找元素,则省略前半部分。
left = mid + 1;
}else if( list[mid] < elem )
{
//如果中间元素小于查找元素,则省略后半部分。
right = mid - 1;
}
}
return -1;
}
注意:
- ASL = log2n
斐波那契查找
分块查找
分块查找又称索引顺序查找。分块查找需要对线性查找表进行分块并建立索引结构。
思想:将线性查找表分块若干块,每块称为一个子表(子表无序,因此子表只能用顺序查找)。各表间满足分块有序,且后表各元素均大于前表。
分块查找还需对分块的线性表,建立索引结构,包含关键字、子表长度和指针。
图示:

算法实现:
struct index //定义块的结构
{
int key; //块的关键字
int start; //块的起始值
int end; //块的结束值
}index_table[4]; //定义结构体数组
int block_search(int key,int a[]) //自定义实现分块查找
{
int i,j;
i=1;
while(i<=3&&key>index_table[i].key) //确定在哪个块中
i++;
if(i>3) //大于分得的块数,则返回0
return 0;
j=index_table[i].start; //j等于块范围的起始值
while(j<=index_table[i].end&&a[j]!=key) //在确定的块内进行顺序查找
j++;
if(j>index_table[i].end) //如果大于块范围的结束值,则说明没有要査找的数,j置0
j = 0;
return j;
}
int main()
{
int i,j=0,k,key,a[16];
printf("请输入15个数:\n");
for(i=1;i<16;i++)
scanf("%d",&a[i]); //输入由小到大的15个数
for(i=1;i<=3;i++)
{
index_table[i].start=j+1; //确定每个块范围的起始值
j=j+1;
index_table[i].end=j+4; //确定每个块范围的结束值
j=j + 4;
index_table[i].key=a[j]; //确定每个块范围中元素的最大值
}
printf("请输入你想査找的元素:\n");
scanf("%d",&key); //输入要查询的数值
k=block_search(key,a); //调用函数进行查找
if(k!=0)
printf("查找成功,其位置是:%d\n",k); //如果找到该数,则输出其位置
else
printf("查找失败!"); //若未找到,则输出提示信息
return 0;
}
注意:
- 子表是无序的,因此子表只能用顺序查找。
- 分块查找具有一定的有序性,即块与块之间有序。
- ASL = ( m + ) + 1 ( m为子表个数,n为查找表的长度)
- 分块查找的ASL既与线性查找表的长度有关,又与所分的子表数目有关。
- 当子表数目 m = 时,ASL最小 ,即 + 1
二叉排序树
性质:
- 若它的左子树不空,则左子树上所有关键字的值均小于其根关键字的值。
- 若它的右子树不空,则右子树上所有关键字的值均大于其根关键字的值。
- 左右子树又是一棵二叉排序树。
算法实现:
BTNOde* BSTSearch(BTNode* p, int key)
{
//p首先指向根结点
while( p != NULL)
{
if( key == p->key)
{
return p;
}else if (key < p->key)
{
// 如果查找值小于根结点则进入左子树查找
p = p->lChild;
}else{
// 如果查找值大于根结点则进入右子树查找
p = p->rChild;
}
}
return NULL; // 查找失败
}
平衡二叉树
B树
B+树
哈希查找
基本概念
哈希查找方法又称杂凑法、散列法。其中,选取的函数称为哈希函数,按照此方法建立的数据元素存储表称哈希表,哈希表中的存储单元的数量称为哈希表长。
思想:
选取一个函数,用数据元素的关键字作为参数,计算该元素的存储地址,该存储位置称为哈希地址,并将数据元素存储在该位置。如果出现冲突,需要进行冲突处理。
哈希函数
- 直接定址法
以关键字的一个线性函数作为数据元素的存储地址。
该方法不会产生冲突,但当关键字跨度较大时会浪费内存。
- 除留取余法
以关键字除以M的余数作为数据元素的存储地址。
M是一个常数,当M是一个素数或小于20的质数时,有利于减少冲突的发生。
- 乘余取整法
-
折叠法
-
数字分析法
-
平方取中法
冲突处理
①:开放定址法
- 线性探测法
注意:
- M为哈希表长度, 1 <= i < M
- d = 1 ,2,3····,M-1
-
二次探测法
②:链地址法
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· .NET Core 中如何实现缓存的预热?
· 从 HTTP 原因短语缺失研究 HTTP/2 和 HTTP/3 的设计差异
· AI与.NET技术实操系列:向量存储与相似性搜索在 .NET 中的实现
· 基于Microsoft.Extensions.AI核心库实现RAG应用
· Linux系列:如何用heaptrack跟踪.NET程序的非托管内存泄露
· TypeScript + Deepseek 打造卜卦网站:技术与玄学的结合
· Manus的开源复刻OpenManus初探
· AI 智能体引爆开源社区「GitHub 热点速览」
· 三行代码完成国际化适配,妙~啊~
· .NET Core 中如何实现缓存的预热?