第十四周项目1验证算法

来源:互联网 发布:linux文件强制锁 编辑:程序博客网 时间:2024/06/09 19:39
1、认真阅读并验证哈希表实施查找的相关算法,写程序建立序列{16, 74, 60, 43, 54, 90, 46, 31, 29, 88, 77}的哈希表,装填因子定为0.8,哈希函数为h(k)=key%p,p=11,采用线性探查法解决冲突。测试中: 
(1)输出建立的哈希表; 
(2)完成关键字为29的元素的查找; 

(3)在上述哈希表中删除关键字为77的元素,再显示哈希表。 

本文是[数据结构基础系列(8):查找]中第11课时[哈希表——散列结构]和第12课时[哈希表的运算]的例程。

这里写图片描述

#include <stdio.h>#define MaxSize 100         //定义最大哈希表长度#define NULLKEY -1          //定义空关键字值#define DELKEY  -2          //定义被删关键字值typedef int KeyType;        //关键字类型typedef char * InfoType;    //其他数据类型typedef struct{    KeyType key;            //关键字域    InfoType data;          //其他数据域    int count;          //探查次数域} HashData;typedef HashData HashTable[MaxSize];        //哈希表类型void InsertHT(HashTable ha,int &n,KeyType k,int p)  //将关键字k插入到哈希表中{    int i,adr;    adr=k % p;    if (ha[adr].key==NULLKEY || ha[adr].key==DELKEY)    //x[j]可以直接放在哈希表中    {        ha[adr].key=k;        ha[adr].count=1;    }    else                    //发生冲突时采用线性探查法解决冲突    {        i=1;                //i记录x[j]发生冲突的次数        do        {            adr=(adr+1) % p;  //此处处理冲突,但有不妥之处。应该%m,但m在这一个系列的解答中,并未作为参数传递进来。见程序后面的讨论            i++;        }        while (ha[adr].key!=NULLKEY && ha[adr].key!=DELKEY);        ha[adr].key=k;        ha[adr].count=i;    }    n++;}void CreateHT(HashTable ha,KeyType x[],int n,int m,int p)  //创建哈希表{    int i,n1=0;    for (i=0; i<m; i++)         //哈希表置初值    {        ha[i].key=NULLKEY;        ha[i].count=0;    }    for (i=0; i<n; i++)        InsertHT(ha,n1,x[i],p);}int SearchHT(HashTable ha,int p,KeyType k)      //在哈希表中查找关键字k{    int i=0,adr;    adr=k % p;    while (ha[adr].key!=NULLKEY && ha[adr].key!=k)    {        i++;                //采用线性探查法找下一个地址        adr=(adr+1) % p;    }    if (ha[adr].key==k)     //查找成功        return adr;    else                    //查找失败        return -1;}int DeleteHT(HashTable ha,int p,int k,int &n)   //删除哈希表中关键字k{    int adr;    adr=SearchHT(ha,p,k);    if (adr!=-1)        //在哈希表中找到该关键字    {        ha[adr].key=DELKEY;        n--;            //哈希表长度减1        return 1;    }    else                //在哈希表中未找到该关键字        return 0;}void DispHT(HashTable ha,int n,int m)    //输出哈希表{    float avg=0;    int i;    printf(" 哈希表地址:\t");    for (i=0; i<m; i++)        printf(" %3d",i);    printf(" \n");    printf(" 哈希表关键字:\t");    for (i=0; i<m; i++)        if (ha[i].key==NULLKEY || ha[i].key==DELKEY)            printf("    ");         //输出3个空格        else            printf(" %3d",ha[i].key);    printf(" \n");    printf(" 搜索次数:\t");    for (i=0; i<m; i++)        if (ha[i].key==NULLKEY || ha[i].key==DELKEY)            printf("    ");         //输出3个空格        else            printf(" %3d",ha[i].count);    printf(" \n");    for (i=0; i<m; i++)        if (ha[i].key!=NULLKEY && ha[i].key!=DELKEY)            avg=avg+ha[i].count;    avg=avg/n;    printf(" 平均搜索长度ASL(%d)=%g\n",n,avg);}int main(){    int x[]= {16,74,60,43,54,90,46,31,29,88,77};    int n=11,m=13,p=13,i,k=29;    HashTable ha;    CreateHT(ha,x,n,m,p);    printf("\n");    DispHT(ha,n,m);    i=SearchHT(ha,p,k);    if (i!=-1)        printf(" ha[%d].key=%d\n",i,k);    else        printf(" 未找到%d\n",k);    k=77;    printf(" 删除关键字%d\n",k);    DeleteHT(ha,p,k,n);    DispHT(ha,n,m);    i=SearchHT(ha,p,k);    if (i!=-1)        printf(" ha[%d].key=%d\n",i,k);    else        printf(" 未找到%d\n",k);    printf(" 插入关键字%d\n",k);    InsertHT(ha,n,k,p);    DispHT(ha,n,m);    printf("\n");    return 0;}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8
  • 9
  • 10
  • 11
  • 12
  • 13
  • 14
  • 15
  • 16
  • 17
  • 18
  • 19
  • 20
  • 21
  • 22
  • 23
  • 24
  • 25
  • 26
  • 27
  • 28
  • 29
  • 30
  • 31
  • 32
  • 33
  • 34
  • 35
  • 36
  • 37
  • 38
  • 39
  • 40
  • 41
  • 42
  • 43
  • 44
  • 45
  • 46
  • 47
  • 48
  • 49
  • 50
  • 51
  • 52
  • 53
  • 54
  • 55
  • 56
  • 57
  • 58
  • 59
  • 60
  • 61
  • 62
  • 63
  • 64
  • 65
  • 66
  • 67
  • 68
  • 69
  • 70
  • 71
  • 72
  • 73
  • 74
  • 75
  • 76
  • 77
  • 78
  • 79
  • 80
  • 81
  • 82
  • 83
  • 84
  • 85
  • 86
  • 87
  • 88
  • 89
  • 90
  • 91
  • 92
  • 93
  • 94
  • 95
  • 96
  • 97
  • 98
  • 99
  • 100
  • 101
  • 102
  • 103
  • 104
  • 105
  • 106
  • 107
  • 108
  • 109
  • 110
  • 111
  • 112
  • 113
  • 114
  • 115
  • 116
  • 117
  • 118
  • 119
  • 120
  • 121
  • 122
  • 123
  • 124
  • 125
  • 126
  • 127
  • 128
  • 129
  • 130
  • 131
  • 132

附:关于上面解法中存在的问题 
  1. 运行上面的程序,结果为 
这里写图片描述 
  结果正确。

  2.改换问题要求。还是这一组数,但哈希函数改为h(k)=k%11,装填因子选0.8,于是存储单元m=11÷0.8=13。期望的结果是: 
这里写图片描述 
  修改main函数,实施测试。改动如下:

int main(){    int x[]= {16,74,60,43,54,90,46,31,29,88,77};    int n=11,m=13,p=11,i,k=29;   //将p修改为11    HashTable ha;    CreateHT(ha,x,n,m,p);    ……}
  • 1
  • 2
  • 3
  • 4
  • 5
  • 6
  • 7
  • 8

  但运行结果中建立的哈希表却是: 
这里写图片描述 
  从代码中找其原因。解决冲突中重新定址的adr=(adr+1)%p应该是adr=(adr+1)%m,应该以存储单元数m为依据,决定是否将下标返回到0。 
  本文开头的课件截图中,也明确示出 di=(di1+1) mod m 。相关的InsertHT函数和SearchHT函数中对应的代码,都应该改过。在修改中,存储单元数m也应该作为参数传递给相关的函数。 
  感谢烟台大学计146-2班杨珺同学指出错误。本文讨论至此,暂不做修改。这可能更有利于读者从我的错误中得到提高。


原创粉丝点击