查找(或检索)是在给定信息集上寻找特定信息元素的过程。
待查找的数据单位(或数据元素)称为记录,在学生管理系统中,一个学生的全部信息称为一条记录。如果这个学生的某个属性可以作为他的标识属性,称为关键字 key。如果这个key值可以最为学生的唯一标识,那么称为 主key。我们就是通过key值,从一堆数据中来检索我们想要的那条记录。称为查找!
不同的应用场合适用不同的方法,查找方法有很多,有顺序查找、折半查找、分块查找、树表查找及Hash表查找等等。本次介绍
总结来说,对于无序的一组数据,通常也只能通过顺序查找,这种一一比较的方法简单粗暴,但如果数据过多的话,效率上就说不过去了。如果选用折半查找,需先对数据记录进行排序(通过主key值的大小),然后利用已排序的数据进行查找,效率较高。但有时数据库中的数据记录是不断变化的,不可能时时刻刻保持已排序的状态,所以有了Hash表排序。
可以对无序记录表查找,但是效率是最低的,查找某记录几乎要扫描整个表,当表长n很大时,会令人无法忍受。
平均查找长度: ASL=O(n)。
算法思路:逐一比较,直到匹配记录输出
int seqsearch(int *a,int key)
{
int i;
for(i=N-1;i>=0;i--)
{
if(key==a[i])
return i;
}
return -1;
}
只能对有序记录表查找,效率相对较高。平均查找长度: ASL=O(log2(n+1)),大大优于O(n)。
算法思路:当记录的key按关系≤或≥有序时,则对给定值k,逐步确定待查记录所在区间,每次将搜索空间减少一半(折半),直到查找成功或失败为止。
int binsearch(int *a,int key)
{
int low,high,mid;
low=0;
high=N-1;
while(low<=high)
{
mid=(low+high)/2;//找到中间位置
if(a[mid]==key)
return mid;//查找成功,返回mid
else if(keymid位置记录的key,则让low=mid+1;
}
return -1;//查找失败,返回-1
}
Hash表,又称散列表、杂凑表。在前面讨论的顺序、折半、分块查找和树表的查找中,其ASL的量级在O(n)~O(log2n)之间
Hash表的查找特点:怎么构造的表就怎么查找,即造表与查找过程统一
Hash表的产生背景
之前的查找方法建立在比较的基础上,随着n的扩大,算法的效率会越来越低。这是因为记录的key与记录的存放地址无关,因而查找只能建立在key的“比较”基础上。
对给定的k,不经任何比较便能获取所需的记录,其查找的时间复杂度为常数级O(C)。这就要求在建立记录表的时候,确定记录的key与其存储地址之间的关系f,即使key与记录的存放地址H相对应
说白了就是记录按照key值存放,key值与地址有函数f的映射关系。这就是Hash表
关于Hash表的讨论关键是两个问题
选取(或构造)Hash函数的方法很多,原则是尽可能将记录均匀分布,以减少冲突现象的发生
hash函数构造方法:直接地址法,数字分析法,平方取中法,叠加法,保留除数法,随机函数法
处理冲突方法:开放地址法、链地址法
这里使用保留除数法构造hash函数,线性探查法处理冲突
算法思路:对给定k,根据造表时选取的H(key)求H(k)。若H(k)单元=^,则查找失败,否则k与该单元存放的key比较,若相等,则查找成功;若不等,则根据设定的处理冲突方法,找下一地址Hi,直到查找到或等于空为止。
程序实现
hash表数据结构
typedef int datatype;
typedef struct hashtbl{
datatype *h;
int length;
}hash_tbl,*hash_tp;
初始化hash表
申请hash表空间
void init_hash(hash_tp *Hp,int m)
{
(*Hp)=(hash_tp)malloc(sizeof(hash_tbl));
if(NULL==*Hp)
{
perror("malloc");
exit(-1);
}
(*Hp)->length=m;
(*Hp)->h=(datatype*)malloc((*Hp)->length*sizeof(datatype));
if(NULL==(*Hp)->h)
{
perror("Malloc");
exit(-1);
}
int i;
for(i=0;i<(*Hp)->length;i++)
{
(*Hp)->h[i]=-1;
}
}
创建hash表
int fun(int m)
{
int i;
for(;m>1;m--)
{
for(i=2;i=m)
return m;
}
return -1;
}
void create_hash(hash_tp hp,datatype *a)
{
int hash_val,i,p;
p=fun(hp->length);
if(p==-1)
exit(-1);
for(i=0;ih[hash_val])!=-1)
hash_val=(hash_val+1)%hp->length;
//3、将记录存储在hash_val的位置
hp->h[hash_val]=a[i];
// hash_show(hp);
}
}
hash查找
int hash_search(hash_tp hp,int key)
{
int hash_val,flag,p;
p=fun(hp->length);
hash_val = key %p;//用除留余数法得到hash地址
while((hp->h[hash_val])!=key)
{
hash_val = (hash_val+1)%hp->length;
flag++;
if(flag==hp->length)
return -1;
}
return hash_val;
}