头歌数据结构,第2关:实现散列查找

本文详细解释了C语言中结构体使用.和->操作符的规则,通过实例说明了如何在结构体和结构体指针之间转换并访问成员。文章还提供了散列表相关代码,强调了理解数据结构和编程实践的重要性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

目录

前言

正文

作者的话

代码

前言

这一篇博客解决你结构体中.和->的疑惑。关于C语言结构体中

& * -> . 在结构体中的应用

这一关,你写的代码也在一直报错吗?我猜测,应该和我一样,使用的HNode或者HNode*一直各种报错。

由于这关同时定义了结构体类型和结构体类型的指针【之前遇到的关卡一般都是定义成指针或者都定义成结构体类型,第一次见这种,如果不能改声明,这就涉及两者间用&和*的相互转换了】,散列查找没啥好说的,很好想明白。但我写完后,测评时一直提示我的代码中包含.和->所在的行是存在问题的,我检查逻辑,并未发现错误,猜测是结构体没用正确,之前对.和->也确实理解的不够透彻。

struct HNode {
    int key; //假设关键码为整数
    HNode* next;
};
struct LHTable {
    HNode* pn;  //指向散列表,每个表结点是独立链表的表头结点.【个人注释:这里是将pn当做一个HNode的结构体数组来用了,并非一个HNode*的指针】
    int n; //散列表的长度,一般取(小于等于数据个数的最大)质数
};

最终看了多篇关于这方面的博客终于弄明白了,我将用简单明了的方式给也对这个知识点抱有疑惑的各位解释清楚【听不明白来线下真实我

正文

用.  需要声明结构体。格式是,结构体类型名+结构体名【HNode Dome】,则直接用.就能访问到结构体Dome中的数据域和指针域。
                【int a = Dome.key;
                  HNode* node = Dome.next; 】
用-> 需要声明结构体类型的指针。【HNode* Dome】,则直接用->来访问指针所指向的相应地址的结构体的数据域和指针域。
                【int a = Dome->key;
                  HNode* node = Dome->next; 】
再通俗的总结一下: .前面的是一个具体结构体,而->前面是一个指针(你应该知道,指针也就是地址)

铺垫了些知识点,重头戏来了!!!!
在一行语句中即有结构体,又有结构体类型的指针,如何赋值或正常引用:[记住&取地址符,和*是一对逆运算符]
在结构体前加上&,就成了指针了,也就可以用->了,在指针前加上*,就变成结构体了,用.来访问域
但要注意一下优先级,不放心就加个括号。且要让等式左右两边输出类型一致【检查一下,不能一边指针,一边不是指针】
【HNode H1; HNode* H2;】
 HNode* H3=(&H1)->next;
 HNode H4=(*H2).next;                                  
 ---------------------------------------------------------------------------------
下面代码中的应用:
pt->pn[i]=*(pt->pn[i].next);        代码第97行  //pt->pn[i]是一个结构体,
pre=&(pt->pn[i]);                   代码第103行 //pre的声明: HNode* pre;

作者的话

对于那些直接找代码的同学,我真心劝诫你,数据结构是很重要的课程,这代码逻辑并不难,学校讲的不会?只会理论,不会代码?推荐去看这个宝藏视频【别问为什么】:UP从0到1带你手撕数据结构全集(C语言版)_哔哩哔哩_bilibili

如果确实很急,把我的先借给你用用,但希望你会重新写一遍【没看答案,自己写的,写的不好 请谅解!!】你应该早听说过数据结构真的真的真的很重要,你也该想想,如果学了这门课不能实践,写不出代码,这不和现实所需,社会所求脱轨吗?找工作呢?【打住,我也是学生,对找工作的要求不太清楚,只是个人主观觉得有问题】

代码

#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和END之间实现你的代码*/
    /*****BEGIN*****/
    if(ILH_FindKey(pt,x))
        return false;
    int i=x%(pt->n);
    if(pt->pn[i].key==0)
        pt->pn[i].key=x;
    else
    {
        HNode* temp=&(pt->pn[i]);
        HNode* p=(HNode*)malloc(sizeof(HNode));
        while(temp->next)
            temp=temp->next;
        temp->next=p;
        p->key=x;
        p->next=NULL;
    }
    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*****/
    if(!ILH_FindKey(pt,x))
        return false;
    int i=x%(pt->n);
    if(pt->pn[i].key==x)
    {
        if(pt->pn[i].next==NULL)
            pt->pn[i].key=0;
        else
            pt->pn[i]=*(pt->pn[i].next);
    }
    else
    {
        HNode* pre;
        HNode* del;
        pre=&(pt->pn[i]);
        del=pre->next;
        while(del->key!=x)
        {
            pre=pre->next;
            del=del->next;
        }
        pre->next=del->next;
        free(del);
    }
    return true;
    /******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");
    }
}

评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

j3ff_

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值