【数据结构与算法】哈希表设计(C\C++)

news2024/10/5 16:25:31

实践要求

1. 问题描述

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


2. 基本要求

假设人名为中国人姓名的汉语拼音形式。待填入哈希表的人名共有30个,取平均查找长度的上限为2。哈希函数用除留余数法构造。用伪随机探测再散列法处理冲突。


3. 测试数据

取读者周围较熟悉的30个人的姓名拼音。


4. 实现提示

如果随机函数自行构造,则应首先调整好随机函数,使其分布均匀。人名的长度均不超过度20个字符。字符的取码方法可直接利用PASCAL语言中的ord函数。可先对过长的人名作折叠处理。


5. 选作内容

  1. 从教科书上介绍的几种哈希函数构造方法中选出适用者并设计几个不同的哈希函数,比较它们的地址冲突率(可以用更大的名字集合作试验)。
  2. 研究这30个人名的特点,努力找一个哈希函数,使得对于不同的拼音名一定不发生地址冲突。
  3. 在哈希函数确定的前题下尝试各种不同处理冲突的方法,考查平均查找长度的变化和造好的哈希表中关键字的聚簇性。

实践报告

1. 题目分析

说明程序设计的任务,强调的是程序要做什么,此外列出各成员分工

程序设计任务:
针对某个集体中人名设计一个哈希表,使得平均查找长度不超过R,并完成相应的建表和查找程序。假设人名为中国人姓名的汉语拼音形式。待填入哈希表的人名共有30个,取平均查找长度的上限为2。哈希函数用除留余数法构造。用伪随机探测再散列法处理冲突。


2. 数据结构设计

说明程序用到的数据结构的定义,主程序的流程及各模块之间的层次关系

该程序主要用到的数据结构是自定义的哈希表,该数据结构包含以下成员:

  1. Person: 人名节点结构体,包含一个 name 字符数组用于存储人名。

  2. HashTable: 哈希表结构体,包含以下成员:

    成员名称解释
    data一个 Person 类型的指针,用于存储哈希表中的数据。
    flags一个整数数组,用于标记哈希表中的位置是否为空。当一个位置有 人名时,对应位置的标记为1;否则,标记为0。
    size哈希表的大小,表示哈希表可以容纳的最大元素数量。

主程序流程图

Created with Raphaël 2.3.0 START Insert names into Hash Table Search for a name in the Hash Table Print the serach result END

3. 程序设计

实现概要设计中的数据类型,对主程序、模块及主要操作写出伪代码,画出函数的调用关系

各模块伪代码

初始化哈希表

// 初始化哈希表
void initHashTable(HashTable *table, int size)
{
    // 为哈希表分配空间
    // 为标记数组分配空间
    // 设置哈希表的大小
    for (int i = 0; i < size; i++)
    {
    // 初始化人名为空
    // 初始化标记数组为0
    }
}

除留余数法

// 哈希函数:除留余数法
int hashFunction(char *name, int size)
{
    int sum = 0;
    for (int i = 0; i < strlen(name); i++)
    {
        // 将人名中每个字符的ASCII码相加
    }
    return sum % size;
}

插入人名到哈希表中

// 插入人名到哈希表中
void insertName(HashTable *table, char *name)
{
    // 计算人名在哈希表中的位置
    int i = 0;
    // 记录发生冲突的次数
    while // 人名发生冲突
    {
        // 发生冲突时,使用伪随机探测再散列法处理
    }
    // 将人名填入哈希表中
    // 标记数组中的位置为1,表示该位置已经有人名
}

查找人名在哈希表中

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    // 计算人名在哈希表中的位置
    int i = 0;
    while // 人名发生冲突
    {
        if// 比较人名是否相同
        {
            return index; // 找到了人名,返回索引位置
        }
        // 发生冲突时,使用伪随机探测再散列法处理
    }
    return NOT_FOUND; // 未找到人名
}

各函数层次关系图

调用
调用
调用
调用
main
findName
insertName
hashFuction

4. 调试分析

程序复杂度分析

1. 空间复杂度
时间复杂度:

  1. 初始化哈希表时间复杂度为 O ( s i z e ) O(size) O(size)
    注:其中 size 是哈希表的大小。
  2. 插入人名到哈希表中的时间复杂度
    平均情况下 O ( 1 ) ,最坏情况下为 O ( s i z e ) 平均情况下O(1),最坏情况下为 O(size) 平均情况下O(1),最坏情况下为O(size)
    这是因为哈希函数的散列操作通常具有 O(1) 的复杂度,但在发生冲突时可能需要执行一系列探测再散列操作,导致最坏情况下的复杂度为 O(size)。
  3. 查找人名在哈希表中的位置的时间复杂度
    平均情况下为 O ( 1 ) ,最坏情况下为 O ( s i z e ) 平均情况下为 O(1),最坏情况下为 O(size) 平均情况下为O(1),最坏情况下为O(size)
    与插入操作类似,平均情况下的复杂度是常数级别,但最坏情况下需要遍历整个哈希表才能找到人名或确定其不存在。

2. 时间复杂度
O ( s i z e ) O(size) O(size)
哈希表数据和标记数组:O(size),其中 size 是哈希表的大小。哈希表数据占用的空间是 O(size),标记数组占用的空间也是 O(size)。

心得体会

使用链表要注意不能使用空指针,不能使用指向未知内存的指针,以及用完指针后要及时释放。否则就会碰到一些莫名其妙的错误。


5. 测试结果

列出测试结果,包括输入和输出

测试结果

测试结果说明:
输入姓名集里面的姓名,
将会输出该姓名在哈希表中的位置。

input

chenxinxin

output

Found at index 47

在这里插入图片描述


6. 用户使用说明

给出主界面及主要功能界面

使用说明

用户运行程序后系统会自动打印各个姓名插入到哈希表中冲突的次数,随后可以输入姓名集合里面的的一个姓名,系统会输出其在哈希表中的位置。
注:姓名集是在源文件中一直写进去的,而不是txt或者文档读入的,故若想修改姓名集合,则需要重写main函数里面的数组。


7. 选作内容

实现了(1),(2),(3)

7.1 (1)的实现

从教科书上介绍的几种哈希函数构造方法中选出适用者并设计几个不同的哈希函数,比较它们的地址冲突率(可以用更大的名字集合作试验)。

解:将书本上的平方去中法与上述的除留取余法进行地址冲突比较,发现平方去中法的冲突率非常高,达到了31.22%。

除留余数法

除留余数法
总冲突次数:12
平均冲突次数:0.4
冲突率:0.013333
在这里插入图片描述

在这里插入图片描述

平方取中法

平方取中法
总冲突次数:281
平均冲突次数:9.366
冲突率:0.312222

在这里插入图片描述
在这里插入图片描述


7.2 (2)的实现

研究这30个人名的特点,努力找一个哈希函数,使得对于不同的拼音名一定不发生地址冲突。

解:根据以下名字集合,总结了三个特点,针对这三个特点实现了一个自定义哈希函数。

//名字集合
"chencaiyi", "chenxinxin", "fangsongjie", "huangjiawei", "huangjunlin", "leiyang",
"luwei", "wangzhanqi", "wuweidong", "longjiajing", "huangweiqin", "chenshangming", "huangtao",
"maixupeng", "chenying", "liujunhui", "chenqingdong", "guoziming", "chenyilong", "libaiyang", "liangdeguang",
"zhangyuxing", "huangyibin", "liuwenlong", "zengzihao", "wangshulian", "zhuzixian", "lidingkun", "caofu", "yuemingju"

  1. 大多数名字遵循“姓+名”或“姓+中间名+名字”的模式。
  2. 有些名字有重复的字符,如chencaiyi,chenxinxni,huangjunlin。
  3. 名称的长度各不相同,从 5 到 12 个字符不等。

因此设计了一个自定义哈希函数,函数如下

// 哈希函数:自定义哈希函数
int hashFunction(char *name, int size)
{
    int hash = 0;
    int nameLength = strlen(name);
    for (int i = 0; i < nameLength; i++)
    {
        hash = (hash * 31 + name[i]) % size;
    }
    return hash;
}


7.3 (3)的实现

在哈希函数确定的前题下尝试各种不同处理冲突的方法,考查平均查找长度的变化和造好的哈希表中关键字的聚簇性。

解:在确定使用(2)所说的自定义哈希函数后,将采用单独链接法来处理冲突的情况。

单独链接法:在此方法中,哈希表中的每个插槽都包含一个链表或其他数据结构,用于存储散列到同一索引的多个元素。发生冲突时,新元素将添加到该索引处的链接列表中。要搜索元素,请在相应的索引处遍历链表,直到找到匹配项。

下面是改动最大的函数findName

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    // 遍历链表查找人名
    PersonNode *currentNode = table->data[index];
    while (currentNode != NULL)
    {
        if (strcmp(currentNode->name, name) == 0)
        {
            return index; // 找到了人名,返回索引位置
        }
        currentNode = currentNode->next;
    }
    return NOT_FOUND; // 未找到人名
}


8. 附录

附录说明:
一共有四个.cpp文件,分别为HashMap.cppHashMap(1).cppHashMap(2).cppHashMap(3).cpp

源程序文件清单:
HashMap.cpp :使用求留取余法的哈希表。
HashMap(1).cpp :使用平方取中法的哈希表。
HashMap(2).cpp :使用自定义哈希方法来改善求留取余法的哈希表。
HashMap(3).cpp :使用单链接法来处理冲突情况来改善HashMap(2).cpp中的程序。

9. 全部代码

HashMap.cpp

/*
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-13 16:38:25
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-14 17:28:58
 * @FilePath: \appe:\C OR C++\code\HashMap.cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HashTABLE_SIZE 61  // 哈希表的大小,选择一个较大的素数
#define MAX_NAME_LENGTH 20 // 人名的最大长度
#define NOT_FOUND -1       // 未找到的标志

typedef struct
{
    char name[MAX_NAME_LENGTH]; // 人名
} Person;

typedef struct
{
    Person *data; // 哈希表的数据
    int *flags;   // 标记哈希表中的位置是否为空
    int size;     // 哈希表的大小
} HashTable;

// 哈希函数:除留余数法
int hashFunction(char *name, int size)
{
    int sum = 0;
    for (int i = 0; i < strlen(name); i++)
    {
        sum += name[i]; // 将人名中每个字符的ASCII码相加
    }
    return sum % size;
}

// 初始化哈希表
void initHashTable(HashTable *table, int size)
{
    table->data = (Person *)malloc(sizeof(Person) * size); // 为哈希表分配空间
    table->flags = (int *)malloc(sizeof(int) * size);      // 为标记数组分配空间
    table->size = size;                                    // 设置哈希表的大小
    for (int i = 0; i < size; i++)
    {
        strcpy(table->data[i].name, ""); // 初始化人名为空
        table->flags[i] = 0;             // 初始化标记数组为0
    }
}
// 插入人名到哈希表中
void insertName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    int conflicts = 0;               // 记录发生冲突的次数
    while (table->flags[index] == 1) // 人名发生冲突
    {
        // 发生冲突时,使用伪随机探测再散列法处理
        i++;
        index = (index + i * i) % table->size;
        conflicts++;
    }
    strcpy(table->data[index].name, name); // 将人名填入哈希表中
    table->flags[index] = 1;               // 标记数组中的位置为1,表示该位置已经有人名

    printf("Inserted %s with %d conflicts.\n", name, conflicts);
}

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    while (table->flags[index] != 0) // 人名发生冲突
    {
        if (strcmp(table->data[index].name, name) == 0) // 比较人名是否相同
        {
            return index; // 找到了人名,返回索引位置
        }
        i++;
        index = (index + i * i) % table->size; // 发生冲突时,使用伪随机探测再散列法处理
    }
    return NOT_FOUND; // 未找到人名
}

int main()
{
    HashTable table;
    initHashTable(&table, HashTABLE_SIZE); // 初始化哈希表

    // 待填入哈希表的人名
    char names[30][MAX_NAME_LENGTH] = {
        "chencaiyi", "chenxinxin", "fangsongjie", "huangjiawei", "huangjunlin", "leiyang",
        "luwei", "wangzhanqi", "wuweidong", "longjiajing", "huangweiqin", "chenshangming", "huangtao",
        "maixupeng", "chenying", "liujunhui", "chenqingdong", "guoziming", "chenyilong", "libaiyang", "liangdeguang",
        "zhangyuxing", "huangyibin", "liuwenlong", "zengzihao", "wangshulian", "zhuzixian", "lidingkun", "caofu", "yuemingju"};

    // 建立哈希表
    for (int i = 0; i < 30; i++)
    {
        insertName(&table, names[i]);
    }

    // 查找程序
    char searchName[MAX_NAME_LENGTH];
    printf("Enter a name to search: "); // 输入要查找的人名
    scanf("%s", searchName);            // 读取人名

    int index = findName(&table, searchName); // 查找人名在哈希表中的位置
    if (index != NOT_FOUND)                   // 找到了人名
    {
        printf("Found at index %d\n", index);
    }
    else // 未找到人名
    {
        printf("Not found\n");
    }

    return 0;
}

HashMap(1).cpp

/*
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-14 17:27:57
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-14 17:28:14
 * @FilePath: \appe:\C OR C++\code\HashMap(1).cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HashTABLE_SIZE 61  // 哈希表的大小,选择一个较大的素数
#define MAX_NAME_LENGTH 20 // 人名的最大长度
#define NOT_FOUND -1       // 未找到的标志

typedef struct
{
    char name[MAX_NAME_LENGTH]; // 人名
} Person;

typedef struct
{
    Person *data; // 哈希表的数据
    int *flags;   // 标记哈希表中的位置是否为空
    int size;     // 哈希表的大小
} HashTable;

// 哈希函数:平方取中法
int hashFunction(char *name, int size)
{
    int nameLength = strlen(name);
    int square = nameLength * nameLength;
    int midDigits = (square / 100) % 100; // 取中间两位数

    return midDigits % size;
}

// 初始化哈希表
void initHashTable(HashTable *table, int size)
{
    table->data = (Person *)malloc(sizeof(Person) * size); // 为哈希表分配空间
    table->flags = (int *)malloc(sizeof(int) * size);      // 为标记数组分配空间
    table->size = size;                                    // 设置哈希表的大小
    for (int i = 0; i < size; i++)
    {
        strcpy(table->data[i].name, ""); // 初始化人名为空
        table->flags[i] = 0;             // 初始化标记数组为0
    }
}

// 插入人名到哈希表中
void insertName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    int conflicts = 0; // 记录发生冲突的次数
    while (table->flags[index] == 1) // 人名发生冲突
    {
        // 发生冲突时,使用平方探测再散列法处理
        i++;
        index = (index + i * i) % table->size;
        conflicts++;
    }
    strcpy(table->data[index].name, name); // 将人名填入哈希表中
    table->flags[index] = 1;               // 标记数组中的位置为1,表示该位置已经有人名

    printf("Inserted %s with %d conflicts.\n", name, conflicts);
}

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    while (table->flags[index] != 0) // 人名发生冲突
    {
        if (strcmp(table->data[index].name, name) == 0) // 比较人名是否相同
        {
            return index; // 找到了人名,返回索引位置
        }
        i++;
        index = (index + i * i) % table->size; // 发生冲突时,使用平方探测再散列法处理
    }
    return NOT_FOUND; // 未找到人名
}

int main()
{
    HashTable table;
    initHashTable(&table, HashTABLE_SIZE);

    // 待填入哈希表的人名
    char names[30][MAX_NAME_LENGTH] = {
        "chencaiyi", "chenxinxin", "fangsongjie", "huangjiawei", "huangjunlin", "leiyang",
        "luwei", "wangzhanqi", "wuweidong", "longjiajing", "huangweiqin", "chenshangming", "huangtao",
        "maixupeng", "chenying", "liujunhui", "chenqingdong", "guoziming", "chenyilong", "libaiyang", "liangdeguang",
        "zhangyuxing", "huangyibin", "liuwenlong", "zengzihao", "wangshulian", "zhuzixian", "lidingkun", "caofu", "yuemingju"};

    // 建立哈希表
    for (int i = 0; i < 30; i++)
    {
        insertName(&table, names[i]);
    }

    // 查找程序
    char searchName[MAX_NAME_LENGTH];
    printf("Enter a name to search: ");
    scanf("%s", searchName);

    int index = findName(&table, searchName);
    if (index != NOT_FOUND)
    {
        printf("Found at index %d\n", index);
    }
    else
    {
        printf("Not found\n");
    }

    return 0;
}

HashMap(2).cpp

/*
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-14 17:29:44
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-14 17:45:38
 * @FilePath: \appe:\C OR C++\code\HashMap(2).cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HashTABLE_SIZE 61  // 哈希表的大小,选择一个较大的素数
#define MAX_NAME_LENGTH 20 // 人名的最大长度
#define NOT_FOUND -1       // 未找到的标志

typedef struct
{
    char name[MAX_NAME_LENGTH]; // 人名
} Person;

typedef struct
{
    Person *data; // 哈希表的数据
    int *flags;   // 标记哈希表中的位置是否为空
    int size;     // 哈希表的大小
} HashTable;

// 哈希函数:自定义哈希函数
int hashFunction(char *name, int size)
{
    int hash = 0;
    int nameLength = strlen(name);

    for (int i = 0; i < nameLength; i++)
    {
        hash = (hash * 31 + name[i]) % size;
    }

    return hash;
}

// 初始化哈希表
void initHashTable(HashTable *table, int size)
{
    table->data = (Person *)malloc(sizeof(Person) * size); // 为哈希表分配空间
    table->flags = (int *)malloc(sizeof(int) * size);      // 为标记数组分配空间
    table->size = size;                                    // 设置哈希表的大小
    for (int i = 0; i < size; i++)
    {
        strcpy(table->data[i].name, ""); // 初始化人名为空
        table->flags[i] = 0;             // 初始化标记数组为0
    }
}

// 插入人名到哈希表中
void insertName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    int conflicts = 0; // 记录发生冲突的次数
    while (table->flags[index] == 1) // 人名发生冲突
    {
        // 发生冲突时,使用平方探测再散列法处理
        i++;
        index = (index + i * i) % table->size;
        conflicts++;
    }
    strcpy(table->data[index].name, name); // 将人名填入哈希表中
    table->flags[index] = 1;               // 标记数组中的位置为1,表示该位置已经有人名

    printf("Inserted %s with %d conflicts.\n", name, conflicts);
}

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置
    int i = 0;
    while (table->flags[index] != 0) // 人名发生冲突
    {
        if (strcmp(table->data[index].name, name) == 0) // 比较人名是否相同
        {
            return index; // 找到了人名,返回索引位置
        }
        i++;
        index = (index + i * i) % table->size; // 发生冲突时,使用平方探测再散列法处理
    }
    return NOT_FOUND; // 未找到人名
}

int main()
{
    HashTable table;
    initHashTable(&table, HashTABLE_SIZE);

    // 待填入哈希表的人名
    char names[30][MAX_NAME_LENGTH] = {
        "chencaiyi", "chenxinxin", "fangsongjie", "huangjiawei", "huangjunlin", "leiyang",
        "luwei", "wangzhanqi", "wuweidong", "longjiajing", "huangweiqin", "chenshangming", "huangtao",
        "maixupeng", "chenying", "liujunhui", "chenqingdong", "guoziming", "chenyilong", "libaiyang", "liangdeguang",
        "zhangyuxing", "huangyibin", "liuwenlong", "zengzihao", "wangshulian", "zhuzixian", "lidingkun", "caofu", "yuemingju"};

    // 建立哈希表
    for (int i = 0; i < 30; i++)
    {
        insertName(&table, names[i]);
    }

    // 查找程序
    char searchName[MAX_NAME_LENGTH];
    printf("Enter a name to search: ");
    scanf("%s", searchName);

    int index = findName(&table, searchName);
    if (index != NOT_FOUND)
    {
        printf("Found at index %d\n", index);
    }
    else
    {
        printf("Not found\n");
    }

    return 0;
}

HashMap(3).cpp

/*
 * @Author: hiddenSharp429 z404878860@163.com
 * @Date: 2023-06-14 17:28:46
 * @LastEditors: hiddenSharp429 z404878860@163.com
 * @LastEditTime: 2023-06-14 17:46:28
 * @FilePath: \appe:\C OR C++\code\HashMap(3).cpp
 * @Description: 这是默认设置,请设置`customMade`, 打开koroFileHeader查看配置 进行设置: https://github.com/OBKoro1/koro1FileHeader/wiki/%E9%85%8D%E7%BD%AE
 */
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

#define HashTABLE_SIZE 61  // 哈希表的大小,选择一个较大的素数
#define MAX_NAME_LENGTH 20 // 人名的最大长度
#define NOT_FOUND -1       // 未找到的标志

typedef struct PersonNode
{
    char name[MAX_NAME_LENGTH]; // 人名
    struct PersonNode *next;    // 指向下一个节点的指针
} PersonNode;

typedef struct
{
    PersonNode **data; // 哈希表的数据
    int size;          // 哈希表的大小
} HashTable;

// 哈希函数:自定义哈希函数
int hashFunction(char *name, int size)
{
    int hash = 0;
    int nameLength = strlen(name);

    for (int i = 0; i < nameLength; i++)
    {
        hash = (hash * 31 + name[i]) % size;
    }

    return hash;
}

// 初始化哈希表
void initHashTable(HashTable *table, int size)
{
    table->data = (PersonNode **)malloc(sizeof(PersonNode *) * size); // 为哈希表分配空间
    table->size = size;                                               // 设置哈希表的大小
    for (int i = 0; i < size; i++)
    {
        table->data[i] = NULL; // 初始化每个槽位为空
    }
}

// 插入人名到哈希表中
void insertName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置

    // 创建新节点
    PersonNode *newNode = (PersonNode *)malloc(sizeof(PersonNode));
    strcpy(newNode->name, name);
    newNode->next = NULL;

    if (table->data[index] == NULL)
    {
        // 槽位为空,直接插入新节点
        table->data[index] = newNode;
    }
    else
    {
        // 槽位非空,遍历链表找到尾节点并插入新节点
        PersonNode *currentNode = table->data[index];
        while (currentNode->next != NULL)
        {
            currentNode = currentNode->next;
        }
        currentNode->next = newNode;
    }

    printf("Inserted %s\n", name);
}

// 查找人名在哈希表中的位置
int findName(HashTable *table, char *name)
{
    int index = hashFunction(name, table->size); // 计算人名在哈希表中的位置

    // 遍历链表查找人名
    PersonNode *currentNode = table->data[index];
    while (currentNode != NULL)
    {
        if (strcmp(currentNode->name, name) == 0)
        {
            return index; // 找到了人名,返回索引位置
        }
        currentNode = currentNode->next;
    }

    return NOT_FOUND; // 未找到人名
}

int main()
{
    HashTable table;
    initHashTable(&table, HashTABLE_SIZE);

    // 待填入哈希表的人名
    char names[30][MAX_NAME_LENGTH] = {
        "chencaiyi", "chenxinxin", "fangsongjie", "huangjiawei", "huangjunlin", "leiyang",
        "luwei", "wangzhanqi", "wuweidong", "longjiajing", "huangweiqin", "chenshangming", "huangtao",
        "maixupeng", "chenying", "liujunhui", "chenqingdong", "guoziming", "chenyilong", "libaiyang", "liangdeguang",
        "zhangyuxing", "huangyibin", "liuwenlong", "zengzihao", "wangshulian", "zhuzixian", "lidingkun", "caofu", "yuemingju"};

    // 建立哈希表
    for (int i = 0; i < 30; i++)
    {
        insertName(&table, names[i]);
    }

    // 查找程序
    char searchName[MAX_NAME_LENGTH];
    printf("Enter a name to search: ");
    scanf("%s", searchName);

    int index = findName(&table, searchName);
    if (index != NOT_FOUND)
    {
        printf("Found at index %d\n", index);
    }
    else
    {
        printf("Not found\n");
    }

    return 0;
}

结束语

  因为是算法小菜,所以提供的方法和思路可能不是很好,请多多包涵~如果有疑问欢迎大家留言讨论,你如果觉得这篇文章对你有帮助可以给我一个免费的赞吗?我们之间的交流是我最大的动力!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/728013.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++——string(2)

作者&#xff1a;几冬雪来 时间&#xff1a;2023年7月7日 内容&#xff1a;C——string内容讲解 目录 前言&#xff1a; 1.string&#xff1a; 1. reserve&#xff1a; 2.resize&#xff1a; 3.assign&#xff1a; 4.insert&#xff1a; 5.erase&#xff1a; 6.rep…

策略模式深度实践——通用的HTTP接口调用

个人主页&#xff1a;金鳞踏雨 个人简介&#xff1a;大家好&#xff0c;我是金鳞&#xff0c;一个初出茅庐的Java小白 目前状况&#xff1a;22届普通本科毕业生&#xff0c;几经波折了&#xff0c;现在任职于一家国内大型知名日化公司&#xff0c;从事Java开发工作 我的博客&am…

【CSS卡片翻转特效】CSS3实现3D旋转动画卡片翻转效果(附源码)

文章目录 写在前面涉及知识点效果展示1、web页面的搭建1&#xff09;创建dom节点2&#xff09;DOM元素添加图片3&#xff09;添加翻转后的文字 2、CSS效果的实现1&#xff09;div本身翻转效果2&#xff09;3D翻转效果完整CSS3实现翻转效果demo代码可以留言邮箱或者自己去百度网…

扒开 TCP 的外衣,看清 TCP 的本质

TCP 非常重要&#xff0c;它的内容很多&#xff0c;今天只能讲解其中的一部分&#xff0c;但足以让你超越 80 % 的编程开发人员对于 TCP 的认知。 本篇内容非常多&#xff0c;非常干&#xff0c;希望你花点时间仔细研究&#xff0c;我相信会对你有所帮助。 1. TCP 协议是什么…

【tomcat】应用服务

准备环境 三台虚拟机 192.168.1.120 192.168.1.122 192.168.1.131 三台虚拟机关闭防火墙 、查看光盘 、检测yun创库 查看JDK是否安装 [rootlocalhost ~]# java -version openjdk version "1.8.0_161" //这是系统自带的rpm方式安装 OpenJDK Runtime Environment…

云端刺点难?这次看看云端地球怎么做

了解像控点与刺点 像控点是直接为摄影测量的控制点加密或测图需要而在实地布设并进行测定的控制点。 刺像控点是把外业采集的像控点的地理坐标与看到这个点的照片相关联的过程。在倾斜摄影建模中&#xff0c;使用像控点进行刺点可以大大提高建模精度。 为什么云端地球可以做…

青岛大学_王卓老师【数据结构与算法】Week04_02_带尾结点的循环链表合并_学习笔记

本文是个人学习笔记&#xff0c;素材来自青岛大学王卓老师的教学视频。 一方面用于学习记录与分享&#xff0c;另一方面是想让更多的人看到这么好的《数据结构与算法》的学习视频。 如有侵权&#xff0c;请留言作删文处理。 课程视频链接&#xff1a; 数据结构与算法基础–…

LLM搭建金融系统

背景&#xff1a; 这篇文章主要给大家介绍如何基于LLM模型配合各种pluging工具&#xff08;这边主要是跟数据连接、检索的工具相关&#xff1a;知识图谱、向量库...)。在开始文章前先讲讲我的观点&#xff1a;大模型的颠覆性应用应该不在于AIGC&#xff0c;而在于数据驱动技术…

python验证公网ip与内网ip

公网IP和内网IP都是用于标识网络设备的地址&#xff0c;但它们有着不同的作用和特点。 公网IP是由互联网服务提供商&#xff08;ISP&#xff09;分配给用户设备的唯一标识符。它是全球范围内唯一的&#xff0c;并且可以被其他网络设备使用来寻找和连接特定的设备。公网IP通常用…

Linux操作系统中命令提示符最后的符号为“#”或“$”

07-Linux操作系统中命令提示符最后的符号为“#”或“$” 1、最后提示符“#”2、最后提示符“$”3、[lwhlocalhost~]中 “ ~” 1、最后提示符“#” 表示管理员身份2、最后提示符“$” 表示不同用户3、[lwhlocalhost~]中 “ ~” 表示当前用户的家目录

安装umi

安装umi 一、安装Node.js&#xff0c;通过node -v查看版本号 二、安装yarn&#xff0c;其中tyarn使用的是npm.taobao.org的源&#xff0c;速度要快一些&#xff08;可以把yarn看做优化了的npm&#xff09; 1. 安装tyarn npm i yarn tyarn -g1 -g&#xff1a;全局安装 2. …

【C++】用Ceres从三维点中拟合三维空间中的圆

任务描述 在三维空间中有N个点&#xff0c;需要得到过这N个点的最优圆&#xff0c;需要估计圆的圆心、半径和法向量&#xff0c;本文提供了一种方法和代码示例&#xff0c;利用Ceres进行非线性拟合&#xff0c;在cpp上开发。 圆心为三维&#xff0c;半径一维&#xff0c;法向…

深入刨析容器(四):深入理解容器镜像

容器通过Namespace和Cgroups将自己与宿主机隔离&#xff0c;那么容器里的进程看到文件系统又是什么样子的呢&#xff1f;容器里的程序应该看到完全独立的文件系统&#xff0c;这样它就可以在自己的容器目录&#xff08;比如 /tmp&#xff09;下进行操作&#xff0c;而完全不会受…

贝莱德CEO力挺比特币!币圈嘲讽:传统金融从嘲笑到开始入场了!

资产管理巨头贝莱德&#xff08;BlackRock&#xff09;首席执行官Larry Fink公开喊话&#xff0c;希望监管者以民主化方式&#xff0c;来看待现货ETF申请。将与监管积极配合&#xff0c;解除他们对现货比特币ETF的疑虑。 六月中旬&#xff0c;贝莱德向美国证券交易委员会&#…

vue3中Cron表达式的使用

效果&#xff1a; <a-form-item label"Cron表达式" name"cron" required><a-input v-show"false" v-model:value"setForm.cron"></a-input><a-button type"primary" size"small" click"…

使用NVCleanstall导致显卡功率被锁至115W问题解决

以拯救者Y9000K为例&#xff0c;显卡功耗最大可以达到165W&#xff0c;但最近更新至最新的显卡驱动后&#xff0c;发现显卡功率被限制到了115W。一度怀疑是老黄做了手脚。 经过一系列测试后发现&#xff0c;是自己操作姿势不对。 NVIDIA Platform Controllers and Framework这…

leetcode极速复习版-第四章字符串

目录 344. 反转字符串 541. 反转字符串II 剑指Offer 05.替换空格 151.翻转字符串里的单词 剑指Offer58-II.左旋转字符串 28.实现 strStr() 459.重复的子字符串 字符串总结 344. 反转字符串 编写一个函数&#xff0c;其作用是将输入的字符串反转过来。输入字符串以字符数组 char…

JAVA jfreechart生成柱状图

JAVA jfreechart生成柱状图 在项目资源评估中&#xff0c;也就是生成word文档里需要根据数据生成柱状图&#xff0c;在网上找到了jfreechart工具包&#xff0c;来生成柱状图&#xff0c;当然他不仅仅只能生成柱状图&#xff0c;还支持折线图、饼状图等等… 过程 导入依赖 &l…

快速创建剪映草稿

实现原理 : JianYingPro 项目文件是 json 的形式存储的,只需要创建draft_content.json,draft_mate_info.json 打开软件后会自动补全。添加一个媒体到轨道顺序 草稿媒体库 -> 内容媒体库-> 轨道片段add_media_to_track 会识别媒体类型,加入到对应轨道。当没有视频轨道时…

哈希表 基础理论

什么是哈希表&#xff1f; 哈希表英文名hash table&#xff0c;国内有一些书籍也翻译为散列表。哈希表是根据关键码的值而直接进行访问的数据结构。 直白来讲&#xff0c;其实数组就是一张哈希表&#xff0c;哈希表中关键码就是数组的索引下标&#xff0c;然后通过下标直接访…