c語言散列表
『壹』 數據結構 哈希表,C語言解答
設計一個哈希表,哈希函數用除留余數法,用開放定址法、線性探測處理沖突,從文本文件讀入30個左右中文人名,每行一人,可用本班學生名單。要求:
1.成功的平均查找長度不超過3,能查找人名,能插入新人名,能顯示當前哈希表中每個元素,每行顯示6個。
2.編寫主函數測試這些功能,並統計實際的平均查找長度。用菜單式操作。
3.如果有餘力,可以增加刪除功能(選做)。
提示:
根據成功的平均查找長度要求和估算公式求出裝填因子α上界及哈希表長度m。
#include <stdio.h>
#include<malloc.h>
#include<string.h>
//#include
#define HASH_LEN 50 //哈希表的長度
#define M 47
#define NAME_NO 30 //人名的個數
typedef struct NAME
{
char *py; //名字的拼音
int k; //拼音所對應的整數
}NAME;
NAME NameList[HASH_LEN];
typedef struct hterm //哈希表
{
char *py; //名字的拼音
int k; //拼音所對應的整數
int si; //查找長度
}HASH;
HASH HashList[HASH_LEN];
/*-----------------------姓名(結構體數組)初始化---------------------------------*/
void InitNameList()
{ int i;
char *f;
int r,s0;
NameList[0].py="chenghongxiu";
NameList[1].py="yuanhao";
NameList[2].py="yangyang";
NameList[3].py="zhanghen";
NameList[4].py="chenghongxiu";
NameList[5].py="xiaokai";
NameList[6].py="liupeng";
NameList[7].py="shenyonghai";
NameList[8].py="chengquan";
NameList[9].py="luqing";
NameList[10].py="gongyunxiang";
NameList[11].py="sunzhenxing";
NameList[12].py="sunrongfei";
NameList[13].py="sunminglong";
NameList[14].py="zhanghao";
NameList[15].py="tianmiao";
NameList[16].py="yaojianzhong";
NameList[17].py="yaojianqing";
NameList[18].py="yaojianhua";
NameList[19].py="yaohaifeng";
NameList[20].py="chengyanhao";
NameList[21].py="yaoqiufeng";
NameList[22].py="qianpengcheng";
NameList[23].py="yaohaifeng";
NameList[24].py="bianyan";
NameList[25].py="linglei";
NameList[26].py="fuzhonghui";
NameList[27].py="huanhaiyan";
NameList[28].py="liudianqin";
NameList[29].py="wangbinnian";
for (i=0;i<NAME_NO;i++)// *求出各個姓名的拼音所對應的整數
{
s0=0;
f=NameList[i].py;
for (r=0;*(f+r) != '\0';r++) //方法:將字元串的各個字元所對應的ASCII碼相加,所得的整數做為哈希表的關鍵字
s0=*(f+r)+s0;
NameList[i].k=s0;
}
}
/*-----------------------建立哈希表---------------------------------*/
void CreateHashList()
{int i; for ( i=0; i<HASH_LEN;i++)//哈希表的初始化 { HashList[i].py=""; HashList[i].k=0; HashList[i].si=0; }
for (i=0; i<NAME_NO;)
{
int sum=0;
int adr=(NameList[i].k) % M; //哈希函數
int d=adr;
if(HashList[adr].si==0) //如果不沖突
{
HashList[adr].k=NameList[i].k;
HashList[adr].py=NameList[i].py;
HashList[adr].si=1;
}
else //沖突
{
do
{
d=(d+((NameList[i].k))%10+1)%M; //偽散列
sum=sum+1; //查找次數加1
}while (HashList[d].k!=0);
HashList[d].k=NameList[i].k;
HashList[d].py=NameList[i].py;
HashList[d].si=sum+1;
}i++;
}
}
/*-------------------------------------查找------------------------------------*/
void FindList()
{ int r;
char name[20]={0};
int s0=0;
int sum=1;
int adr;
int d;
printf("\n\n請輸入姓名的拼音: "); //輸入姓名
scanf("%s",name);
for ( r=0;r<20;r++) //求出姓名的拼音所對應的整數(關鍵字)
s0+=name[r];
adr=s0 % M; //使用哈希函數
d=adr;
if(HashList[adr].k==s0) //分3種情況進行判斷
printf("\n姓名:%s 關鍵字:%d 查找長度為: 1",HashList[d].py,s0);
else if (HashList[adr].k==0)
printf("無該記錄!");
else
{
int g=0;
do
{
d=(d+s0%10+1)%M; //偽散列
sum=sum+1;
if (HashList[d].k==0)
{
printf("無記錄! ");
g=1;
}
if (HashList[d].k==s0)
{
printf("\n姓名:%s 關鍵字:%d 查找長度為:%d",HashList[d].py,s0,sum);
g=1;
}
}while(g==0);
}
}
/*--------------------------------顯示哈希表----------------------------*/
void Display()
{int i; float average=0; printf("\n\n地址\t關鍵字\t\t搜索長度\tH(key)\t\t拼音 \n"); //顯示的格式 for( i=0; i<15; i++) { printf("%d ",i); printf("\t%d ",HashList[i].k); printf("\t\t%d ",HashList[i].si); printf("\t\t%d ",(HashList[i].k)%M); printf("\t %s ",HashList[i].py); printf("\n"); }
// printf("按任意鍵繼續顯示...\n"); //由於數據比較多,所以分屏顯示(以便在Win9x/DOS下能看到所有的數據)
// getch();
for( i=15; i<30; i++)
{
printf("%d ",i);
printf("\t%d ",HashList[i].k);
printf("\t\t%d ",HashList[i].si);
printf("\t\t%d ",(HashList[i].k)%M);
printf("\t %s ",HashList[i].py);
printf("\n");
}
// printf("按任意鍵繼續顯示...\n");
// getch();
for( i=30; i<40; i++)
{
printf("%d ",i);
printf("\t%d ",HashList[i].k);
printf("\t\t%d ",HashList[i].si);
printf("\t\t%d ",(HashList[i].k)%M);
printf("\t %s ",HashList[i].py);
printf("\n");
}
//printf("按任意鍵繼續顯示...\n");
//getch();
for( i=40; i<50; i++)
{
printf("%d ",i);
printf("\t%d ",HashList[i].k);
printf("\t\t%d ",HashList[i].si);
printf("\t\t%d ",(HashList[i].k)%M);
printf("\t %s ",HashList[i].py);
printf("\n");
}
for (i=0;i<HASH_LEN;i++)
{average+=HashList[i].si; average/=NAME_NO; printf("\n\n平均查找長度:ASL(%d)=%f \n\n",NAME_NO,average); }
}
/*--------------------------------主函數----------------------------*/
void main()
{
/* ::SetConsoleTitle("哈希表操作"); //Windows API函數,設置控制台窗口的標題
HANDLE hCon = ::GetStdHandle(STD_OUTPUT_HANDLE); //獲得標准輸出設備的句柄
::SetConsoleTextAttribute(hCon, 10|0); //設置文本顏色
*/
printf("\n------------------------哈希表的建立和查找----------------------");
InitNameList();
CreateHashList ();
while(1)
{ char ch1;
printf("\n\n");
printf(" 1. 顯示哈希表\n");
printf(" 2. 查找\n");
printf(" 3. 退出\n");
err:
scanf("%c",&ch1);
if (ch1=='1')
Display();
else if (ch1=='2')
FindList();
else if (ch1=='3')
return;
else
{
printf("\n請輸入正確的選擇!");
goto err;
}
}
}