一. 查找的基本概念
- 在哪里找?
----------------查找表
- 查找表是由同一类型的数据元素(或记录)构成的集合。由于“集合”中的元素之间存在着松散的关系,因此查找表是一种应用灵便的结构。
- 什么是查找?
- 根据给定的某个值,在查找表中确定一个关键字等于给定值的数据元素(或记录)
- 什么是关键字?
- 用来标识一个数据元素(或记录)的某个数据项的值
- 主关键字:可唯一地标识一个记录的关键字
- 次关键字:反之,用以识别若干记录的关键字
- 查找成功否?
- 在查找表中确定一个其关键字等于给定值的数据元素
- 若查找表中存在这样一个记录,则查找成功
- 查找结果给出整个记录的信息,或指示该记录在查找表中的位置
- 否则,查找不成功
- 查找结果给出空记录或空指针
- 查找的目的
- 查询某个特定的数据元素是否在查找表中
- 检索某个特定的数据元素的各种属性
- 在查找表中插入一个数据元素
- 删除查找表中的某个数据元素
查找表的分类:
1. 静态查找表:仅做查询操作
2. 动态查找表:作插入和删除操作
评价查找算法的优劣:
平均比较长度(ASL):关键字的平均比较次数
二. 线性表的查找
1. 顺序查找(线性查找)
- 顺序表或线性链表表示的静态链表
- 表内元素无序
// a 为数组,n 为数组长度,key 为要查找的关键字
int Sequential_Search(int *a,int n,int key)
{
int i;
for(i=0;i<=n;i++)
{
if(a[i] == key)
{
return i;
}
}
return 0;
}
优化:
数据较多时,效率更高
int Sequential_Search2(int *a,int n,int key)
{
int i;
a[0] = key; //设置 a[0] 为key的值,称为哨兵
i = n;
while(a[i] != key)
{
i--; // a[1]~a[n]
}
return i; //返回0,则查找失败
}
2. 有序表查找(折半查找)
- 线性表必须有序排列
- 线性表必须采用顺序储存
- 对线性链表无效,因为无法知晓 mid 在何处
思路:
在有序表中,取中间记录作为比较对象,若中间记录与给定值相同则查找成功;若给定值小于中间记录,则在中间记录的左边半区继续查找;若给定值大于中间记录,则在中间记录的右边半区继续查找;
mid = (low + high)/2
若 key < mid: high = mid -1;
若 key > mid: low = mid +1;
若 key > mid: 找到
int Binary_Search(int *a,int n,int key)
{
int low,mid,high;
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;
}
}
return 0;
}
3. 插值查找
替换了折半查找中的mid
int Binary_Search2(int *a,int n,int key)
{
int low,mid,high;
low = 1;
high = n;
while(low <= high)
{
mid = (key - a[low]) / (a[high] - a[low]);
if( key < a[mid])
{
high = mid - 1;
}
else if( key > a[mid])
{
low = mid +1;
}
else
{
return mid;
}
}
return 0;
}
4. 分块查找
分块查找又称索引顺序查找