//衆神雲集、羣魔亂舞、以一抵百、砥礪前行//8622 哈希查找

題目描述

Description 使用哈希函數:H(k)=3k MOD length,並採用開放定址法處理衝突。試對輸入的關鍵字序列構造哈希表,哈希表長度爲length,求等概率情況下查找成功的平均查找長度,並設計構造哈希表的完整的算法。本題給出部分代碼,請補全Hash函數和解決衝突的collison函數。
#include"malloc.h" /
malloc()等 /
#include"stdlib.h" /
exit() */
#include"stdio.h"
#define EQ(a,b) ((a)==(b))
#define SUCCESS 1
#define UNSUCCESS 0
#define NULLKEY -1 /哈希表無元素時值爲-1/
typedef int ElemType;
int length;
typedef struct
{
ElemType elem; / 數據元素存儲基址,動態分配數組 /
int count; /
當前數據元素個數 */
}HashTable;

void InitHashTable(HashTable H)
{ /
操作結果: 構造一個長度爲length的哈希表,length爲全局變量 */
int i;
(H).count=0; / 當前元素個數爲0 /
(H).elem=(ElemType)malloc(length
sizeof(ElemType));
if(!(H).elem)
exit(0); /
存儲分配失敗 /
for(i=0;i<length;i++)
(H).elem[i]=NULLKEY; / 未填記錄的標誌 /
}
unsigned Hash(ElemType K)
{ /
一個簡單的哈希函數
/

}
void collision(int *p) /*線性探測再散列 /
{ /
開放定址法處理衝突 */

}
int SearchHash(HashTable H,ElemType K,int *p,int c)
{ /
在開放定址哈希表H中查找關鍵碼爲K的元素,若查找成功,以p指示待查數據 /
/
元素在表中位置,並返回SUCCESS;否則,以p指示插入位置,並返回UNSUCCESS /
/
c用以計衝突次數,其初值置零,供建表插入時參考。算法9.17 */
p=Hash(K); / 求得哈希地址 */
while(H.elem[*p]!=NULLKEY&&!EQ(K,H.elem[p]))
{ /
該位置中填有記錄,並且關鍵字不相等 */
(*c)++;
if(c<length)
collision§; /
求得下一探查地址p */
else
break;
}
if EQ(K,H.elem[p])
return SUCCESS; /
查找成功,p返回待查數據元素位置 /
else
return UNSUCCESS; /
查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置 */
}
int InsertHash(HashTable H,ElemType e)
{ /
查找不成功時插入數據元素e到開放定址哈希表H中,並返回查找長度 */
int c,p;
c=0;
if(SearchHash(H,e,&p,&c)) / 表中已有與e有相同關鍵字的元素 /
printf(“哈希表中已有元素%d。\n”,e);
else{ /
插入e */
(*H).elem[p]=e;
++(H).count;
}
return c+1; /查找長度爲衝突次數加1/
}
void TraverseHash(HashTable H)
{ /
按哈希地址的順序打印哈希表,無元素位置用X表示 /
int i;
printf(“HashTable Address:0~%d\n”,length-1);
for(i=0;i<length;i++)
if(H.elem[i]==NULLKEY) /
有數據 */
printf(“X “);
else
printf(”%d “,H.elem[i]);
printf(”\n”);
}
main()
{
float i=0,j=0;
ElemType e;
HashTable H;
//printf(“Input Table length:”);
scanf("%d",&length);
InitHashTable(&H);
//printf(“Input key words sequence, -1 conclusion input:”);
scanf("%d",&e);
while(e!=-1)
{
j ++; /j記錄輸入元素個數/
i = i + InsertHash(&H,e); /i記錄查找長度的和/
scanf("%d",&e);
}
TraverseHash(H);
printf(“Average search length=%f\n”,i/j);
}

輸入格式
第一行:輸入哈希表的長度;
第二行:輸入關鍵字序列,用空格分隔,-1結束(-1不作爲關鍵字)。

輸出格式
第一行:輸出哈希表裏的數據,未使用的單元用X表示;
第二行:輸出平均查找長度,格式爲"Average search length="。

輸入樣例
11
22 41 53 46 30 13 1 67 -1

輸出樣例
22 X 41 30 1 53 46 13 67 X X
Average search length=2.000000

題解

哈希函數即爲題目所給公式,H(k)=3k MOD length。
解決衝突的辦法是用開放定址法中的線性探測再散列。我們將增量序列當成每次增加1,則處理衝突的函數爲
p=(*p+1)%length,注意要取模,不可以超過哈希表的表長。

代碼如下:

//------------------------------Hash Table--------------------------------//
//*            //-------衆神雲集、羣魔亂舞、以一抵百、砥礪前行---------//       *//
//-----------------------------Acmer LEO 到此一遊------------------------------//
#include"malloc.h" /* malloc()等 */
#include"stdlib.h" /* exit() */
#include"stdio.h"
#define EQ(a,b) ((a)==(b))
#define SUCCESS 1
#define UNSUCCESS 0
#define NULLKEY -1 /*哈希表無元素時值爲-1*/
typedef int ElemType;
int length;
typedef struct
{
   ElemType *elem; /* 數據元素存儲基址,動態分配數組 */
   int count; /* 當前數據元素個數 */
}HashTable;
void InitHashTable(HashTable *H)
 { /* 操作結果: 構造一個長度爲length的哈希表,length爲全局變量 */
   int i;
   (*H).count=0; /* 當前元素個數爲0 */
   (*H).elem=(ElemType*)malloc(length*sizeof(ElemType));
   if(!(*H).elem)
     exit(0); /* 存儲分配失敗 */
   for(i=0;i<length;i++)
     (*H).elem[i]=NULLKEY; /* 未填記錄的標誌 */
}
unsigned Hash(ElemType K)
{ /* 一個簡單的哈希函數*/
return 3*K%length;
}
void collision(int *p) /*線性探測再散列 */
{ /* 開放定址法處理衝突 */
*p=(*p+1)%length;
}
int SearchHash(HashTable H,ElemType K,int *p,int *c)
{  /* 在開放定址哈希表H中查找關鍵碼爲K的元素,若查找成功,以p指示待查數據 */
   /* 元素在表中位置,並返回SUCCESS;否則,以p指示插入位置,並返回UNSUCCESS */
   /* c用以計衝突次數,其初值置零,供建表插入時參考。算法9.17 */
   *p=Hash(K); /* 求得哈希地址 */
   while(H.elem[*p]!=NULLKEY&&!EQ(K,H.elem[*p]))
   { /* 該位置中填有記錄,並且關鍵字不相等 */
     (*c)++;
     if(*c<length)
	   collision(p); /* 求得下一探查地址p */
     else
       break;
   }
   if EQ(K,H.elem[*p])
     return SUCCESS; /* 查找成功,p返回待查數據元素位置 */
   else
     return UNSUCCESS; /* 查找不成功(H.elem[p].key==NULLKEY),p返回的是插入位置 */
}
int InsertHash(HashTable *H,ElemType e)
{ /* 查找不成功時插入數據元素e到開放定址哈希表H中,並返回查找長度 */
   int c,p;
   c=0;
   if(SearchHash(*H,e,&p,&c))   /* 表中已有與e有相同關鍵字的元素 */
     printf("哈希表中已有元素%d。\n",e);
   else{ /* 插入e */
     (*H).elem[p]=e;
     ++(*H).count;
   }
   return c+1; /*查找長度爲衝突次數加1*/
}
void TraverseHash(HashTable H)
 { /* 按哈希地址的順序打印哈希表,無元素位置用X表示 */
   int i;
   for(i=0;i<length;i++)
     if(H.elem[i]==NULLKEY)
       printf("X ");
	 else
		 printf("%d ",H.elem[i]);
	 printf("\n");
}
main()
{
	float i=0,j=0;
	ElemType e;
	HashTable H;
	scanf("%d",&length);
	InitHashTable(&H);
	scanf("%d",&e);
	while(e!=-1)
	{
		j++;  /*j記錄輸入元素個數*/
		i = i + InsertHash(&H,e);  /*i記錄查找長度的和*/
		scanf("%d",&e);
	}
	TraverseHash(H);
	printf("Average search length=%f\n",i/j);
}
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章