散列表查找
散列表的存储结构
#define Max 12
typedef struct{
int key;
}HashTable[Max];
函数:散列表的查找(采用线性探测法处理冲突)
输入:散列表的结构体数组变量地址HashTable HT,和要查找的关键字key。该结构体变量的成员有关键字key,类型为int。
输出:若查找成功返回查找到的关键字在散列表的下标,查找失败返回-1。
优化目标:无。
分析:若采用的是二次探测法处理冲突就使用第二个函数。散列表技术有很好的平均性能,优于一些传统的技术。线性探测的优点是只要散列表未填满,总能找到一个不发生冲突的地址,缺点是会产生二次聚集现象(即在处理冲突过程中发生的两个第一个散列地址不同记录争夺同一个后继散列地址);而二次探测法可以避免二次聚集现象,但是不能保证一定找到不发生冲突的地址。
函数一采用线性探测法处理冲突的查找
int SearchHash(HashTable HT,int key){
int H0 = H(key);
if(HT[H0].key == NULLKEY){
return -1;
}
else if(HT[H0].key == key){
return H0;
}
else{
int i;
for(i = 1;i<Max;i++){
int Hi = (H0+i)%Max;
if(HT[Hi].key == NULLKEY){
return -1;
}
else if(HT[Hi].key == key){
return Hi;
}
}
return -1;
}
}
函数二采用二次探测法处理冲突的查找
int SearchHash_2(HashTable HT,int key){
int H0 = H(key);
if(HT[H0].key == NULLKEY){
return -1;
}
else if(HT[H0].key == key){
return H0;
}
else{
int i;
for(i = 1;i<Max;i++){
int Hi;
Hi = (H0+int(pow(i,2)))%Max;
if(HT[Hi].key == NULLKEY){
return -1;
}
else if(HT[Hi].key == key){
return Hi;
}
Hi = (H0-int(pow(i,2)))%Max;
if(HT[Hi].key == NULLKEY){
return -1;
}
else if(HT[Hi].key == key){
return Hi;
}
}
return -1;
}
}
利用散列表查找写程序
输入:依次输入散列表的元素值,以0为结束条件。
输出:利用第一种函数在散列表的查找结果。
优化目标:无。
该散列表的创建也是采用线性探测的方法创建的。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
#define Max 12
#define NULLKEY 0
typedef struct{
int key;
}HashTable[Max];
int H(int key){
return (key%10);
}
void CreateHash(HashTable &HT){
int i,key;
for(i = 0;i<Max;i++){
HT[i].key = NULLKEY;
}
for(i = 0;i<Max;i++){
printf("请输入第%d个元素(0为结束):",i+1);
scanf("%d",&key);
if(key == NULLKEY){
break;
}
int H0 = H(key);
if(HT[H0].key == NULLKEY){
HT[H0].key =key;
continue;
}
int k;
for(k = 1;k<Max;k++){
int Hi = (H0+k)%Max;
if(HT[Hi].key == NULLKEY){
HT[Hi].key = key;
break;
}
}
}
}
void PrintHash(HashTable HT){
int i;
for(i = 0;i<Max;i++){
printf("%d ",HT[i].key);
}
printf("\n");
}
int SearchHash(HashTable HT,int key){
int H0 = H(key);
if(HT[H0].key == NULLKEY){
return -1;
}
else if(HT[H0].key == key){
return H0;
}
else{
int i;
for(i = 1;i<Max;i++){
int Hi = (H0+i)%Max;
if(HT[Hi].key == NULLKEY){
return -1;
}
else if(HT[Hi].key == key){
return Hi;
}
}
return -1;
}
}
int main(){
HashTable HT;
//开始创建散列表
CreateHash(HT);
//输出散列表
PrintHash(HT);
int i;
printf("请输入所要查找的数:");
scanf("%d",&i);
int k = SearchHash(HT,i);
printf("%d在hash表的位置为:%d\n",i,k);
return 0;
}
结果:
请输入第1个元素(0为结束):2
请输入第2个元素(0为结束):8
请输入第3个元素(0为结束):31
请输入第4个元素(0为结束):20
请输入第5个元素(0为结束):19
请输入第6个元素(0为结束):18
请输入第7个元素(0为结束):53
请输入第8个元素(0为结束):27
请输入第9个元素(0为结束):0
20 31 2 53 0 0 0 27 8 19 18 0
请输入所要查找的数:27
27在hash表的位置为:7
问题:写出折半查找的递归算法。初始调用时,low为1,high为ST.length。
算法思想:根据查找的起始位置和终止位置,将查找序列一分为二,判断所查找的关键字在那一部分,然后用新的序列起始位置和终止位置递归求解。
输入:顺序表的结构体变量地址SSTable ST,要查找的关键字key,折半查找的起始位置low,终止位置high。该结构体变量的成员有一维整型数组elem表示顺序表内元素;顺序表长度length,类型为int。
输出:无。
优化目标:无。
分析:二叉排序树插入的基本过程就是查找,所以时间复杂度同查找一样是O()。
typedef struct{
int *elem;
int length;
}SSTable;
int BinSearchRec(SSTable ST,int key,int low,int high){
if(low>high){
return -1;
}
int mid = (low + high)/2;
if(ST.elem[mid] == key) {
return mid;
}
else if(ST.elem[mid]>key){
return BinSearchRec(ST,key,low,mid-1);
}
else{
return BinSearchRec(ST,key,mid+1,high);
}
}
今天主要是复习了一下散列表的查找,然后并且给折半查找算法提出新的方法,利用递归来解决,明天准备复习一下各种排序算法。