educoder 实训---实现散列查找

任务描述

本关要求通过补全函数ILH_InsKeyILH_DelKey来分别实现插入和删除操作。

相关知识

本关讨论散列存储,散列函数使用除留余数法,冲突解决方法采用独立链表地址法。假设有 8 个关键码: 7 , 15 , 23 , 31 , 12 , 14 , 10 , 17 ,采用散列函数hash(key)=key%7,其存储结构图如图 1 所示,它由 7 个独立链表组成,散列值相同的关键码在同一个链表里,独立链表的头结点组成散列表,一共 7 行,编号 0 , 1 , … , 6 。独立链表的每个结点是一个 struct HNode 结构,其定义如下:

 
 
  1. struct HNode {
  2. int key; //假设关键码为整数
  3. HNode* next;
  4. };

在散列表中,如果表项的key字段等于 0 (假设有效的关键码值不等于 0 ),则表示该行是一条空链表,例如图 1 中编号为 4 和编号为 6 的行。

散列表的开始地址保存在pn中,散列表的行数为n(图 1 中,n=7),将pnn组织成结构:

 
 
  1. struct LHTable {
  2. HNode* pn; //指向散列表,每个表结点是独立链表的表头结点
  3. int n; //散列表的长度,一般取(小于等于数据个数的最大)质数
  4. };

定义如下操作,各操作函数的功能详见下面给出的代码文件 indLnkHash.cpp 的代码框架:

 
 
  1. LHTable* ILH_Create(int n);
  2. void ILH_Free(LHTable* pt);
  3. bool ILH_InsKey(LHTable* pt, int x);
  4. bool ILH_FindKey(LHTable* pt, int x);
  5. bool ILH_DelKey(LHTable* pt, int x);
  6. void ILH_Print(LHTable *pt);

编程要求

本关的编程任务是补全 step2/indLnkHash.cpp 文件中的ILH_InsKeyILH_DelKey函数来分别实现插入和删除操作。

  • 具体请参见后续测试样例。

 代码如下

#include <stdio.h>

#include <stdlib.h>

#include <time.h>

#include "indLnkHash.h"

LHTable* ILH_Create(int n)

//创建散列表, n为表长度,最佳取值:n取小于等于数据个数的最大质数

{

    HNode* pn=(HNode*)malloc(sizeof(HNode)*n);

    for (int i=0; i<n; i++) {

        pn[i].key=0;

        pn[i].next=NULL;

    }

    LHTable* pt=(LHTable*)malloc(sizeof(LHTable));

    pt-> pn=pn;

    pt->n=n;

    return pt;

}

void ILH_Free(LHTable* pt)

//释放散列表

{

    if (pt==NULL) return;

    for (int i=0; i<pt->n; i++) {

        HNode* curr=pt->pn[i].next;

        while (curr) {

            HNode* next=curr->next;

            free(curr);

            curr=next;

        }

    }

    free(pt->pn);

    free(pt);

}

bool ILH_InsKey(LHTable* pt, int x)

//插入关键码x

//返回true,表示插入成功

//返回false,表示插入失败(关键码已经存在)

{

  

  /*****BEGIN*****/

    int a=0;

    HNode* p=new HNode;

    HNode* s;

   p->key=x;

    p->next=NULL;

    a=x%pt->n;

     s=pt->pn[a].next;

     if(!ILH_FindKey(pt, x))

     {

    if(pt->pn[a].key==0)

    pt->pn[a].key=x;

    else if(pt->pn[a].next==NULL)

    {

    pt->pn[a].next=p;

    }

    else if(pt->pn[a].next->next==NULL)

    {

       pt->pn[a].next->next=p; 

    }

    

 }

      else

     return false;  

return true;

    /******END******/

    /*请不要修改[BEGIN,END]区域外的代码*/

}

bool ILH_FindKey(LHTable* pt, int x)

//查找关键码x

//返回true表示找到

//返回false表示没找到

{

    int d=x%pt->n;

    if (pt->pn[d].key==0) {

        return false;

    }

    else if (pt->pn[d].key==x) 

        return true;

    HNode* curr=pt->pn[d].next;

    while (curr && curr->key!=x) curr=curr->next;

    if (curr) return  true;

    else return false;

}

bool ILH_DelKey(LHTable* pt, int x)

//删除关键码

//返回true表示该关键码存在,且成功删除

//返回false表示该关键码不存在

{

    /*请在BEGIN和END之间实现你的代码*/

    /*****BEGIN*****/

     HNode* p;

    HNode* s;

     int d;

     d=x%pt->n;

     p=pt->pn[d].next;

     if(ILH_FindKey( pt, x))

     {

     

     if(pt->pn[d].next->key==x)

     {

        pt->pn[d].next=pt->pn[d].next->next;

         

     }

     }

     else

     return false;

       

return true;

   

    /******END******/

    /*请不要修改[BEGIN,END]区域外的代码*/

}

   

   

bool ILH_DelKey(LHTable* pt, int x)

//删除关键码

//返回true表示该关键码存在,且成功删除

//返回false表示该关键码不存在

{

    /*请在BEGIN和END之间实现你的代码*/

    /*****BEGIN*****/

    

    /******END******/

    /*请不要修改[BEGIN,END]区域外的代码*/

}

void ILH_Print(LHTable *pt)

{

    for (int i=0; i<pt->n; i++) {

        printf("%5d:", i);

        if (pt->pn[i].key) {

            printf("%d", pt->pn[i].key);

            HNode* curr=pt->pn[i].next;

            while (curr) {

                printf("->%d", curr->key);

                curr=curr->next;

            }

            printf("\n");

        }

        else 

            printf("-\n");

    }

}

注意:本题链表插入从后面插入,于我们前面学习链表插入,从前面的插入不一样。

猜你喜欢

转载自blog.csdn.net/weixin_52563520/article/details/121727454
今日推荐