前言
`
查找表是由同一类型的数据元素构成的集合。例如电话号码簿和字典都可以看作是一张查找表。
一般对于查找表有以下几种操作:
在查找表中查找某个具体的数据元素;
在查找表中插入数据元素;
从查找表中删除数据元素;
一、哈希表是什么?
哈希表的建立同函数类似,把函数中的 x 用查找记录时使用的关键字来代替,然后将关键字的值带入一个精心设计的公式中,就可以求出一个值,用这个值来表示记录存储的哈希地址。即:
数据的哈希地址=f(关键字的值)。
二、使用步骤
1.建立哈希表
代码如下(示例):
#define MAX 16
// node data
typedef struct{
int key;
}SqNode;
// sequence list
typedef struct{
SqNode r[MAX];
int length;
}SqList;
2.功能实现
代码如下(示例):
// quick sort function
int Partition(SqList *L, int low, int high){ // partitio big - pivotloc - small
L->r[0] = L->r[low];
int pivotkey = L->r[low].key;
while(low<high){
while(low < high && L->r[high].key >= pivotkey){
high--;
}
L->r[low] = L->r[high];
while(low < high && L->r[low].key <= pivotkey){
low++;
}
L->r[high] = L->r[low];
}
L->r[low] = L->r[0];
return low;
}
void QSort(SqList *L, int low, int high){ // sort
if(low < high){
int pivotloc = Partition(L, low, high);
QSort(l, low, pivotloc - 1); // left
QSort(L, pivotloc + 1, high); // right
}
}
void QuickSort(SqList *L){
QSort(L, 1, L->length);
}
int main(int argc, char *argv[])
{
SqList * L = (SqList *)malloc(sizeof(SqList));
if(!L) return -1;
int n, a[] = {1,5,7,8,3,5,9,4,1,0};
n = sizeof(a) / sizeof(int);
printf("a-length:%d ", n);
L->length = n;
for(int i= 1; i < n; i++){
L->r[i].key = a[i-1];
}
QuickSort(L);
printf("sort later:");
for(int i = 1; i < L->length; i++){
printf("%d ", L->r[i].key);
}
puts("");
return 0;
}
总结
在构造哈希表的过程中,由于冲突的产生,使得哈希表的查找算法仍然会涉及到比较的过程,因此对于哈希表的查找效率仍需以平均查找长度来衡量。
在哈希表的查找过程中需和给定值进行比较的关键字的个数取决于以下 3 个因素:
哈希函数:哈希函数的“好坏”取决于影响出现冲突的频繁程度。但是一般情况下,哈希函数相比于后两种的影响,可以忽略不计。
处理冲突的方式:对于同一组关键字,设定相同的哈希函数,使用不同的处理冲突的方式得到的哈希表是不同的,表的平均查找长度也不同。
哈希表的装填因子:在一般情况下,当处理冲突的方式相同的情况下,其平均查找长度取决于哈希表的装满程度:装的越满,插入数据时越有可能发生冲突;反之则越小。
装填因子=哈希表中数据的个数/哈希表的长度,用字符 α 表示(是数学符号,而不是字符 a)。装填因子越小,表示哈希表中空闲的位置就越多。
经过计算,在假设查找表中的所有数据的查找概率相等的情况下,对于表长为 m,数据个数为 n 的哈希表:
其查找成功的平均查找长度约为:-1/α * ln(1-α)
其查找不成功的平均查找长度约为:1/(1-α)
通过公式可以看到,哈希表的查找效率只同装填因子有关,而同哈希表中的数据的个数无关,所以在选用哈希表做查找操作时,选择一个合适的装填因子是非常有必要的。。