数据结构:查找算法

实现哈希表的构造和查找算法,要求:用除留余数法构造哈希函数,分别采用二次探测再散列、链地址法解决冲突。

//
// Created by CHAO on 2021-12-19.
//
//实现哈希表的构造和查找算法,要求:用除留余数法构造哈希函数,分别采用二次探测再散列、链地址法解决冲突。
#include<stdio.h>
#include<stdlib.h>
#include<math.h>
typedef struct node {
    int key;
    struct node *next;
} keytype;

typedef struct {
    keytype elem[100];
    int length;   //当前的长度
    int size;     //哈希表的总长
} Hashtable;

int a=0,b=0;
int twohash(int i, int wei)  //二级探测处理冲突
{
    if (i % 2 != 0)
        wei += pow(++a, 2);
    else
        wei -= pow(++b, 2);
    return wei;
}

int hash(Hashtable h, int key)   //放入数据无冲突
{
    return key%(h.size);
}


void creat(Hashtable *h) {
    int key, t, p;
    printf("请输入哈希表的长度和数据的长度:\n");
    scanf("%d%d", &h->size, &h->length);
    for (int i = 0; i < h->size; i++)  //初始化将哈希表中的关键字都置为-1,代表此存储位为空
        h->elem[i].key = 0;
    printf("请输入数据:\n");
    for (int j = 0; j < h->length; j++) {
        scanf("%d", &key);
        p = hash(*h, key);
        if (h->elem[p].key == 0)
            h->elem[p].key = key; //放入数据无冲突
        else   //二级探测解决
        {
            int count = 1;//记录探测次数,1 -1 4 -4
            t = p; //当前下标
            while (h->elem[p].key != 0 && h->elem[p].key != key)
                //当前下标有元素且不等于key
            {
                p = twohash(count, t);
                count++;
                if (p >= h->size)  //超过下标继续循环
                {
                    p = p % h->size;
                }
                if (p < 0) {    //小于下标
                    p += h->size;
                }
            }
            a = b = 0;
            h->elem[p].key = key;
        }
    }
}


void createLink(Hashtable *h) {  //领接表形式
    int key, t, p;
    printf("请输入哈希表的长度和数据的长度:\n");
    scanf("%d%d", &h->size, &h->length);
    for (int i = 0; i < h->size; i++)  //
    {
        h->elem[i].key = 0;
        h->elem[i].next=NULL;
    }
    printf("请输入数据:\n");
    for (int j = 0; j < h->length; j++)
    {
        scanf("%d", &key);
        p = key%h->size;
        if (h->elem[p].key==0)
            h->elem[p].key = key; //放入数据无冲突
        else
        {
            if ( h->elem[p].key != key)
            {
                keytype *xin = h->elem[p].next;
                keytype *new = (keytype *) malloc(sizeof(keytype));
                new->key = key;
                new->next = NULL;
                if (xin == NULL)  //第二个元素
                    h->elem[p].next=new;
                else
                {
                    while (xin->next != NULL)
                        xin = xin->next;
                    xin->next = new;
                }
            }
        }
    }
}


void printhash(Hashtable *h)    //打印
{
    int i;
    for (i = 0; i < h->size; i++)
        printf("%-4.2d", i);
    printf("\n");
    for (i = 0; i < 2 * h->size; i++)
        printf("--");
    printf("\n");
    for (i = 0; i < h->size; i++)
        printf("%-4.2d", h->elem[i].key);
}

void printhashLink(Hashtable *h)    //打印
{

    int qq=0;
    for (int i = 0; i < h->size; i++)
    {
        printf("%-4.2d%d ",qq++, h->elem[i].key);
        keytype  *pp=h->elem[i].next;
        while (pp!=NULL){
            printf("%d ",pp->key);
            pp=pp->next;
        }
        printf("\n");
    }
}


int SearchHash(Hashtable H,int k){  //二级探测写法寻找
    int  p,i=0,t=0;
    p=hash(H,k);  //求位置
    t=p;
    while(H.elem[p].key!=0&&(k!=H.elem[p].key)) //该地址中有记录且关键字不同
    {
        p=twohash(i,t); // 用二次探测法求的下一个探测的地址
        i++;
    }
    if(k==H.elem[p].key)
        return p;
    else
        return 0;
}

int searchLink(Hashtable H,int key){   //领接表写法
    int p=0;
    p=hash(H,key);  //求位
    if(H.elem[p].key==key)
        return p;
    else   //该地址中有记录且关键字不同
    {
        keytype *xin=H.elem[p].next;
        while(xin!=NULL)
        {
            if(xin->key==key)   //循环判断
                return p;
            xin=xin->next;
        }
    }
    return 0;
}


int main() {

    int key,c;
    int choice=0;
    printf("请选择探索的类型,(1为二次探测,2为链探测)\n");
    scanf("%d",&choice);
    if(choice==1) {
        Hashtable t;
        creat(&t);
        printf("输出哈希表:\n\n");
        printhash(&t);
        printf("\n");
        printf("\n请输入要查找记录的关键字:");
        scanf("%d",&key);
        c=SearchHash(t,key);
        if(c==0)
            printf("没有找到该记录!\n");
        else
            printf("该记录的位置是:%d\n",c);
        return 0;
    } else if(choice==2) {
        Hashtable s;
        createLink(&s);
        printhashLink(&s);
        printf("\n请输入要查找记录的关键字:");
        scanf("%d", &key);
        getchar();
        c = searchLink(s, key);
        if (c == 0)
            printf("没有找到该记录!\n");
        else
            printf("该记录的位置是:%d\n", c);
        return 0;
    }
}

1.先输入需要哪种方法解决冲突,然后会调用函数根据不同的方法创建哈希表,后输入需要查找的数据,这时就会直接用对应的探测方法查找。要注意输入的格式,下面给出一组输入:
探测方式:1
哈希表长度及数据个数:13 5
数据:1 2 12 13 25
查找的值:25
在这里插入图片描述在这里插入图片描述
在这里插入图片描述

  • 0
    点赞
  • 7
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

江景.

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

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

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

打赏作者

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

抵扣说明:

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

余额充值