查找的原理
查找概念
- 设记录表L=(R1,R2,R3…Rn),其中R(1<=i<=n)为记录,对给定的某个值k,在表L中确定key=k的记录的过程,称为查找。
- 若表中存在一个记录Ri的key=k,记为Ri.key=k,则查找成功,返回该记录在表L中的序号i(或Ri的地址),否则(查找失败)返回0(或空地址NULL)。
顺序表的查找
折半查找:对给定值k,逐步确定待查记录所在区间,每次将搜索空间减少一半(折半),直到查找成功或失败为止。
设两个游标low,high,分别指向当前待查找表的上界(表头)和下界(表尾),mid指向中间元素。
Hash表的查找:对给定的k,不经任何比较便能获取所需记录,其查找的时间复杂度为常数级O©。当腰查找key=k的记录时,通过关系f就 可以得到相应的记录的地址而获取记录,从而免去了key的比较过程。这个关系f就是所谓的hash函数(或成为散列函数),记为H(key)。它实际上就是一个地址映射函数,其自变量为key,函数值为记录的存储地址(或你的hash地址)。不同的key可能得到同一个hash地址,即当key1!=key2时,可能有H(key1)=H(key2),此时key1和key2 为同义词,这种现象称为“冲突”,或“碰撞”,因为一个数据单位只能存放一条记录。一般,选取hash函数只能做到使冲突尽可能减少,却不可能完全避免,这就要求再出现冲突之后,寻找适当的方法来解决冲突记录存放的问题。
选取(或构造)hash函数的方法有很多,原则是尽可能将记录均匀分配,以减少冲突的发生。以下有几种常用的方法:
直接地址法,平方取中法,叠加法,保留余数法。
保留余数法:又称为质数除余法,设Hash表空间长度为m,选取一个不大于m的质数p,令:H(key)=key%p
若取p=19(质数),同样对上给定的key集合k,有key:28,35,63,77,105 H(key)=key%19:9,16,6,1,10 H(key)的随机读就好多了。
处理冲突的方法:选取随机度好的hash函数可以减少冲突的发生,一般来讲不能完全避免冲突,设hash表地址空间为0~m-1(表长为m).
在地址j的前面或者后面找一个空闲单元存放冲突的记录,或将冲突的记录拉成链表。
还有一个因素就是表的装填因子&(阿尔法),&=n/m,其中m为表长,n 为表中记录个数,一般&在0.7-0.8之间,使表保持一定的空闲余量,以减少冲突聚积现象。
开放地址法:当发生冲突时,在H(key)的前后找一个空闲单元来存放冲突的记录,即在H(key)的基础上获取下一个地址:Hi=(H(key)+di)%m; m为表长,%运算是保证Hi落在【0,m-1]区间,di为地址增量,di的取法有很多种。
(1)di=1,2,3,....(m-1)---------------------------称为线性探查法
(2)1的平方,-1的平方,2的平方,-2的平方-----------称为二次探查法
设记录的key集合k={23,34,14,38,46,16,68,15,07,31,26}记录数n=11
H(key)=key%13
Hi(H(key)+di)%15; di=1,2,3,4....(m-1)
链式地址法:设H(key)取值范围(值域)为【0,m-1],建立头指针向量HP[m],HP[i](0<=i<=m-1)初值为空。
设H(key)=key%13,k={23,34,14,38,46,16,68,15,07,31,26}.,链存储冲突。键值对(键(key),值(H(key))
链式地址法解决冲突的优点:无聚集现象,删除表中数据容易实现。
hash.h
#ifdef_HASH_H
#define _HASH_H
#define N 15
typedef int datatype ;
typedef struct node{
datatype key;
datatype value;
strcut node *next;
}listnode ,*linklist;
typedef strcut {
listnode data[N];
}hash;
hash *hash_create();
int hash_insert(hash *HT,datatype key);
linklist *hash_search(hash *HT,datatype key);
#endif
hash.c
#include<stdio.h>
#include"hash.h"
#include<string.h>
#include<stdlib.h>
hash *hash_create()
{
if((HT=(hash *)malloc(sizeof(hash)))==NULL){
printf("malloc failed\n");
return NULL;
}
memset(HT,0,sizeof(hash));
return HT;
}
int hash_insert(hash *HT,datatype key)
{
linklist p;
if(HT==NULL){
printf("HT is null\n");
return -1;
}
if((p=(linklist )malloc(sizeof(listnode)))==NULL){
printf("malloc is failed\n");
return -1;
}
p->key=key;
p->vlue=key%N;
p->next=NULL;
q=&(HT->data[key%N]);
while(q->next&&q->next->key<p->key){
q=q->next;
}
p->next=q->next;
q->next=p;
return 0;
}
linklist *hash_search(hash *HT,datatype key)
{
linklist p;
if(HT==NULL){
printf("HT is null\n");
return -1;
}
p=&(HT->data[key%N]); //头结点
while(p->next&&p->next->ke!=key){
p=p->next;
}
if(p->next==NULL){
return NULL;
}else{
printf("found\n");
return p->next;
}
}
test.c
#include<stdio.h>
#include"hash.h"
int main(int argc,char *argv[])
{
hash *HT;
int data[]={23,34,14,38,46,16,68,15,07,31,26};
int i;
linklist r;
if(HT==NULL){
return -1;
}
for(i=0;i<sizeof(data)/sizeof(int);i++){
hash_insert(HT,data[i]);
}
printf("input:);
scanf("%d",&key);
r=hash_search(HT,key);
if(r==NULL)
printf("r not found\n");
else
printf("found:%d %d\n",key,r->key);
return 0;
}
排序
快速排序
#include<stdio.h>
#include<stdlib.h>
#define N 15
int compare(const void *pl,const void *p2)
int quick_sort(int *data,int low,int high);
int partion(int *data,int low,int high);
int main(int argc,char *argv[])
{
int data[N]={0};
int i;
srandom(10);
for(i=0;i<N;i++){
data[i]=random()%100;
}
for(i=0;i<N;i++){
printf("%d ",data[i]);
puts("");
}
//quick_sort(data,0,N-1);
qsort(data,N,sizeof(int),&compare);
for(i=0;i<N;i++){
printf("%d ",data[i]);
puts("");
}
return 0;
}
int partion(int *data,int low,int high)
{
int temp=data[low];
while(low<high){
while(lox<high &&temp<data[high]){
high--;
}
data[low]=data[high];
while(low<high&&temp>=data[high]){
low++;
}
data[high]=data[low];
}
data[low]=temp;
return low;
}
int quick_sort(int *data,int low,int high)
{
int t;
if(data==NULL){
return -1;
}
if(low>=high){
return 0;
}
t=partion(data,low,high);
quick_sort(data,low,t-1);
quick_sort(data,t+1,high);
return 0;
}
int compare(const void *p1,const void *p2)
{
return (*(const void *)p1-*(const void *)p2);
}