数据结构实训——哈希表设计

1 课题描述

针对某个集体中人名设计一个哈希表,使得平均查找长度不超过2,并完成相应的建表和查表程序。

2 问题分析和任务定义

1假设人名为中国人姓名的汉语拼音形式。待填入哈希表的人名共有30个,取平均查找长度的上限为2

2哈希函数用除留余数法构造,用线性探测再散列法或链地址法处理冲突。

3 在输入人名过程中能自动识别非法输入,并给与非法输入的反馈信息要求重新输入。

4)查找成功时,显示姓名及关键字,并计算和输出查找成功的平均查找长度

3 逻辑设计

1)数据类型:

对于名字中包含的信息,名字的拼音使用字符串类型保存,由拼音字母ascll构成的关键字使用整数型保存。对于哈希表所包含的信息,姓名使用字符串类型保存,关键字使用整数型保存,哈希表中的元素使用整数类型保存。

struct name///名字结构体

{

    char s[30];

    int v;///ascll码值之和

} NAME[N];

struct hashs///哈希表结构体

{

    char name[30];///名字

    int key;///关键字

    int sum;///哈希表中含有的元素个数

} HASH[M];

 

2)抽象数据类型:

ADT Hash {

数据对象DD是具有相同特征的数据元素的集合。各数据元素均含有类型相同,可唯一标识数据元素的关键字。

数据关系R:数据元素同属一个集合。

init()

操作结果:初始化姓名表。

creathash()

操作结果:建立哈希表。

displayhash()

操作结果:显示哈希表。

display()

操作结果:显示姓名表。

searchhash()

操作结果:查找姓名。

}ADT Hash

 

3)模块功能:

功能上主要分为初始化姓名表,构建哈希表,显示姓名表,显示哈希表,从哈希表中

查找姓名这五大功能。其中构建哈希表使用除留余数法构建,并用线性探测再散列的方法解决冲突。

 

4 详细设计

{定义相应的存储结构并写出各函数的伪码算法。在这个过程中,要综合考虑系统功能,使得系统结构清晰、合理、简单和易于调试,抽象数据类型的实现尽可能做到数据封装,基本操作的规格说明尽可能明确具体。详细设计的结果是对数据结构和基本操作做出进一步的求精,写出数据存储结构的类型定义,写出函数形式的算法框架}

const int N=30;

const int M=50;

struct name///名字结构体

{

    char s[30];

    int v;///ascll码值之和

} NAME[N];

struct hashs///哈希表结构体

{

    char name[30];///名字

    int key;///关键字

    int sum;///哈希表中含有的元素个数

} HASH[M];

 

<1>初始化函数:void init()

读取姓名信息,初始化姓名表。

<2>创建哈希表函数:void creathash()

将读取信息建立的姓名表建立哈希表。

<3>演示哈希表函数:void displayhash()

打印哈希表中的信息。

<4>演示姓名表函数:void display()

打印姓名表中的信息。

<5>查找哈希表中的姓名函数 void searchhash()

按照输入的姓名查找其在哈希表中的位置,并打印信息。

 

5 程序代码

#include<cstdio>
#include<cstring>
#include<algorithm>
using namespace std;
const int N=30;
const int M=50;
struct name///名字结构体
{
    char s[30];
    int v;///ascll码值之和
} NAME[N];
struct hashs///哈希表结构体
{
    char name[30];///名字
    int key;///关键字
    int sum;///哈希表中含有的元素个数
} HASH[M];
void init()///初始化
{
    int i,j,sum;
    for(i=0; i<N; i++)
    {
        NAME[i].v=0;
    }
    strcpy(NAME[0].s,"chenliang");//陈亮
    strcpy(NAME[1].s,"chenyuanhao");//陈元浩
    strcpy(NAME[2].s,"chengwenliang");//程文亮
    strcpy(NAME[3].s,"dinglei");//丁磊
    strcpy(NAME[4].s,"fenghanzao");//冯汉枣
    strcpy(NAME[5].s,"fuzongkai");//付宗楷
    strcpy(NAME[6].s,"hujingbin");//胡劲斌
    strcpy(NAME[7].s,"huangjianwu");//黄建武
    strcpy(NAME[8].s,"lailaifa");//赖来发
    strcpy(NAME[9].s,"lijiahao");//李嘉豪
    strcpy(NAME[10].s,"liangxiaocong");//梁晓聪
    strcpy(NAME[11].s,"linchunhua");//林春华
    strcpy(NAME[12].s,"liujianhui");//刘建辉
    strcpy(NAME[13].s,"luzhijian");//卢志健
    strcpy(NAME[14].s,"luonan");//罗楠
    strcpy(NAME[15].s,"quegaoxiang");//阙高翔
    strcpy(NAME[16].s,"sugan");//苏淦
    strcpy(NAME[17].s,"suzhiqiang");//苏志强
    strcpy(NAME[18].s,"taojiayang");//陶嘉阳
    strcpy(NAME[19].s,"wujiawen");//吴嘉文
    strcpy(NAME[20].s,"xiaozhuomin");//肖卓明
    strcpy(NAME[21].s,"xujinfeng"); //许金峰
    strcpy(NAME[22].s,"yanghaichun");//杨海春
    strcpy(NAME[23].s,"yeweixiong");//叶维雄
    strcpy(NAME[24].s,"zengwei");//曾玮
    strcpy(NAME[25].s,"zhengyongbin");//郑雍斌
    strcpy(NAME[26].s,"zhongminghua");//钟明华
    strcpy(NAME[27].s,"chenliyan");//陈利燕
    strcpy(NAME[28].s,"liuxiaohui");//刘晓慧
    strcpy(NAME[29].s,"panjinmei");//潘金梅
    for(i=0; i<N; i++)
    {
        sum=0;
        for(j=0; j<strlen(NAME[i].s); j++)
        {
            sum=sum+(NAME[i].s[j]-'a');
        }
        NAME[i].v=sum;///名字字母ascll码之和
    }
}
void creathash()///构造哈希表
{
    int i,j;
    int n,m,counts;
    for(i=0; i<M; i++)
    {
        strcpy(HASH[i].name,"0");
        HASH[i].key=0;
        HASH[i].sum=0;
    }
    for(i=0; i<N; i++)
    {
        counts=1;
        n=(NAME[i].v)%47;
        m=n;
        if(HASH[n].sum==0)///不冲突
        {
            strcpy(HASH[n].name,NAME[i].s);
            HASH[n].key=NAME[i].v;
            HASH[n].sum=1;
        }
        else///如果发生了冲突
        {
            while(1)
            {
                m=(m+(NAME[i].v%10)+1)%47;
                counts++;
                if(HASH[m].key==0)
                {
                    break;
                }
            }
            strcpy(HASH[m].name,NAME[i].s);
            HASH[m].key=NAME[i].v;
            HASH[m].sum=counts;
        }
    }
    return ;
}
void searchhash()
{
    char name[30];
    int i,sum,n,m,counts;
    sum=0;
    n=0;
    counts=1;
    printf("请输入要查找人的姓名拼音:\n");
    scanf("%s",&name);
    for(i=0; i<strlen(name); i++)
    {
        sum+=(name[i]-'a');
    }
    n=sum%47;
    m=n;
    if(strcmp(HASH[n].name,name)==0)
    {
        printf("姓名:%s 关键字:%d 查找长度:1\n",HASH[n].name,sum);
    }
    else if(HASH[n].sum==0)
    {
        printf("没有找到这条记录!!!\n");
    }
    else
    {
        while(1)
        {
            m=(m+(sum%10)+1)%47;///哈希函数
            counts++;
            if(strcmp(HASH[m].name,name)==0)
            {
                printf("姓名:%s 关键字:%d 查找长度:%d\n",HASH[m].name,sum,counts);
                break;
            }
            if(HASH[m].key==0)
            {
                printf("没有找到这条记录!!!\n");
                break;
            }
        }
    }
}
void displayhash()///演示哈希表
{
    int i,sum;
    float ave;
    ave=0.0;
    sum=0;
    printf("\n地址\t关键字\t\t搜索长度\t姓名\n");
    for(i=0; i<M; i++)
    {
        printf("%d",i);
        printf("\t%d",HASH[i].key);
        printf("\t\t%d",HASH[i].sum);
        printf("\t%s",HASH[i].name);
        printf("\n");
    }
    for(i=0; i<M; i++)
    {
        sum+=HASH[i].sum;
    }
    ave=((sum)*1.0)/N;
    printf("\n");
    printf("平均查找长度ASL(%d)=%.3lf\n",N,ave);
    return ;
}
void display()
{
    int i;
    for(i=0; i<30; i++)
    {
        printf("\n\t关键字\t\t姓名\n");
        printf("\t%d",NAME[i].v);
        printf("\t%s",NAME[i].s);
    }
    return ;
}
int menu()
{
    printf("\n\n");
    printf("                *****汉字姓名拼音哈希表展示查找系统*****\n");
    printf("                ***1.展示姓名拼音和关键字            ***\n");
    printf("                ***2.展示哈希表                      ***\n");
    printf("                ***3.查找关键字                      ***\n");
    printf("                ***4.退出                            ***\n");
    printf("                ****************************************\n");
    printf("\n");
    return 0;
}
int main()
{
    int i,n;
    int flag;
    flag=1;
    while(1)
    {
        menu();

        if(flag==1)
        {
            init();
            creathash();
            flag=0;
        }
        scanf("%d",&n);
        getchar();
        if(n<1||n>4)
        {
            printf("输入有误,请重新输入!!!\n");
            continue;
        }
        else
        {
            if(n==1)
            {
                printf("展示所准备的姓名拼音及其所组成的关键字:\n");
                display();
            }
            else if(n==2)
            {
                displayhash();
            }
            else if(n==3)
            {
                searchhash();
            }
            else if(n==4)
            {
                return 0;
            }
        }

    }
    return 0;
}

6 程序调试与测试

1)打印姓名表:

 

2)打印哈希表

 

 

3)查找姓名:

 

 

posted @ 2019-01-11 20:08  王陸  阅读(5425)  评论(7编辑  收藏  举报