用C++使用带头单向非循环链表,实现一个哈西桶

用C++使用带头单向非循环链表,实现一个哈西桶
在C++中使用带头单向非循环链表来实现哈希桶是一种常见的做法,特别是在实现哈希表时。哈希桶是哈希表的基本存储单元,用于存储具有相同哈希值的元素。以下是一个简单的示例,展示了如何使用带头单向非循环链表来实现哈希桶。

首先,我们定义一个节点结构来表示链表中的每个节点:


 #include <iostream>
#include <list>

template <typename K, typename V>
struct Node {
    K key;
    V value;
    Node* next;

    Node(const K& k, const V& v) : key(k), value(v), next(nullptr) {}
};

然而,为了简化实现并利用C++标准库的功能,我们可以直接使用std::list来代替手动实现的链表。std::list是一个双向链表,但在这里我们只会用到它单向遍历的能力,并且它会处理节点的内存管理。为了模拟带头单向非循环链表的行为,我们可以在每个哈希桶内部维护一个空的哨兵节点(头节点),其next指针指向第一个实际存储数据的节点。

接下来,我们定义哈希桶结构:

 template <typename K, typename V>
class HashBucket {
private:
    Node<K, V>* head; // 哨兵节点(头节点)

public:
    HashBucket() {
        head = new Node<K, V>(K(), V()); // 创建一个空的哨兵节点
        head->next = nullptr;
    }

    ~HashBucket() {
        Node<K, V>* current = head->next;
        while (current != nullptr) {
            Node<K, V>* next = current->next;
            delete current;
            current = next;
        }
        delete head;
    }

    void insert(const K& key, const V& value) {
        Node<K, V>* newNode = new Node<K, V>(key, value);
        
        // 插入到链表头部(为了简化,这里不保持顺序)
        newNode->next = head->next;
        head->next = newNode;
    }

    bool search(const K& key, V& result) {
        Node<K, V>* current = head->next;
        while (current != nullptr) {
            if (current->key == key) {
                result = current->value;
                return true;
            }
            current = current->next;
        }
        return false;
    }

    bool remove(const K& key) {
        Node<K, V>* current = head;
        while (current->next != nullptr) {
            if (current->next->key == key) {
                Node<K, V>* toDelete = current->next;
                current->next = toDelete->next;
                delete toDelete;
                return true;
            }
            current = current->next;
        }
        return false;
    }
};

注意:上面的remove函数有一个逻辑错误,因为current应该从head->next开始遍历,而不是从head开始(因为head是哨兵节点)。此外,为了更贴近带头单向非循环链表的概念,我们通常不会在链表中删除节点时释放头节点,因为头节点是固定存在的。下面是修正后的remove函数:

 bool remove(const K& key) {
        Node<K, V>* current = head->next;
        Node<K, V>* prev = head;
        while (current != nullptr) {
            if (current->key == key) {
                prev->next = current->next;
                delete current;
                return true;
            }
            prev = current;
            current = current->next;
        }
        return false;
    }

最后,我们可以定义一个哈希表来使用这些哈希桶:
使用类模板,传入函数作为函数的参数

 template <typename K, typename V>
class HashTable {
private:
    HashBucket<K, V>* buckets;
    size_t bucketCount;
    size_t (*hashFunction)(const K&);

public:
    HashTable(size_t bucketCount, size_t (*hashFunction)(const K&))
        : bucketCount(bucketCount), hashFunction(hashFunction) {
        buckets = new HashBucket<K, V>[bucketCount];
    }

    ~HashTable() {
        delete[] buckets;
    }

    void insert(const K& key, const V& value) {
        size_t bucketIndex = hashFunction(key) % bucketCount;
        buckets[bucketIndex].insert(key, value);
    }

    bool search(const K& key, V& result) {
        size_t bucketIndex = hashFunction(key) % bucketCount;
        return buckets[bucketIndex].search(key, result);
    }

    bool remove(const K& key) {
        size_t bucketIndex = hashFunction(key) % bucketCount;
        return buckets[bucketIndex].remove(key);
    }
};

为了使用这个哈希表,你需要提供一个哈希函数,例如:

 size_t stringHashFunction(const std::string& str) {
    size_t hash = 0;
    for (char c : str) {
        hash = hash * 31 + c;
    }
    return hash;
}

然后你可以这样创建和使用哈希表:

 int main() {
    HashTable<std::string, int> hashTable(10, stringHashFunction);
    hashTable.insert("one", 1);
    hashTable.insert("two", 2);

    int value;
    if (hashTable.search("one", value)) {
        std::cout << "Found 'one' with value " << value << std::endl;
    } else {
        std::cout << "'one' not found" << std::endl;
    }

    hashTable.remove("one");
    if (!hashTable.search("one", value)) {
        std::cout << "'one' has been removed" << std::endl;
    }

    return 0;
}

请注意,这个示例是为了教学目的而简化的。在实际应用中,你可能需要考虑哈希冲突的处理(例如链地址法或开放地址法)、哈希表的动态扩容、以及更高效的哈希函数等因素。

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

检索增强生成 和思维链 结合: 如何创建检索增强思维链 (RAT)?

论文地址&#xff1a;https://arxiv.org/pdf/2403.05313 Github地址&#xff1a;https://github.com/CraftJarvis/RAT 想象一下&#xff0c;一个人工智能助手可以像莎士比亚一样写作&#xff0c;像专家一样推理。这听起来很了不起&#xff0c;对吧&#xff1f;但是&#xff0…

Fabric链码部署测试

参考链接&#xff1a;运行 Fabric 应用程序 — Hyperledger Fabric Docs 主文档 (hyperledger-fabric.readthedocs.io) &#xff08;2&#xff09;fabric2.4.3部署运行自己的链码 - 知乎 (zhihu.com) Fabric2.0测试网络部署链码 - 辉哥哥~ - 博客园 (cnblogs.com) 1.启动测试…

如何单独安装 MATLAB 工具箱

很多时候由于 MATLAB 太大而选择安装一些 Toolbox&#xff0c;但用着用着发现要用到某个没有安装的 Toolbox&#xff0c;这时候就需要再单独安装这个 Toolbox&#xff0c;下面提供两种方法。 本文以安装 系统辨识工具箱 System Identification Toolbox 为例。 方法一&#xf…

Anaconda/Pytorch/PyCharm/Jupyter安装及使用

1.ANACONDA安装 Anaconda 是全球领先的数据科学与机器学习平台&#xff0c;专为开发者、数据分析师设计。通过 Anaconda&#xff0c;您可以轻松管理数据环境、安装依赖包&#xff0c;快速启动数据分析、机器学习项目。 丰富的 Python 数据科学库&#xff1a;Anaconda 集成了常…

RocketMQ消费者如何消费消息以及ack

1.前言 此文章是在儒猿课程中的学习笔记&#xff0c;感兴趣的想看原来的课程可以去咨询儒猿课堂 这篇文章紧挨着上一篇博客来进行编写&#xff0c;有些不清楚的可以看下上一篇博客&#xff1a; https://blog.csdn.net/u013127325/article/details/144934073 2.broker是如何…

【Logstash02】企业级日志分析系统ELK之Logstash 输入 Input 插件

Logstash 使用 Logstash 命令 官方文档 https://www.elastic.co/guide/en/logstash/current/first-event.html #各种插件 https://www.elastic.co/guide/en/logstash/current/input-plugins.html https://www.elastic.co/guide/en/logstash/current/filter-plugins.html htt…

【设计模式】 基本原则、设计模式分类

设计模式 设计模式是软件工程中的一种通用术语&#xff0c;指的是针对特定问题的经过实践验证的解决方案。设计模式并不是最终的代码实现&#xff0c;而是描述了如何解决某一类问题的思路和方法。 如果熟悉了设计模式&#xff0c;当遇到类似的场景&#xff0c;我们可以快速地…

【AI学习】Transformer深入学习(二):从MHA、MQA、GQA到MLA

前面文章&#xff1a; 《Transformer深入学习&#xff08;一&#xff09;&#xff1a;Sinusoidal位置编码的精妙》 一、MHA、MQA、GQA 为了降低KV cache&#xff0c;MQA、GQA作为MHA的变体&#xff0c;很容易理解。 多头注意力&#xff08;MHA&#xff09;&#xff1a; 多头注…

【DevOps】Jenkins部署

Jenkins部署 文章目录 Jenkins部署资源列表基础环境一、部署Gilab1.1、安装Gitlab1.2、修改配置文件1.3、加载配置文件1.4、访问Gitlab1.5、修改root登录密码1.6、创建demo测试项目1.7、上传代码1.8、验证上传的代码 二、部署Jenkins所需软件2.1、部署JDK2.2、部署Tomcat2.3、部…

Node.js - 文件操作

1. 文件写入 文件写入是计算机非常常见的操作&#xff0c;下载文件&#xff0c;安装软件&#xff0c;保存程序日志&#xff0c;视频录制等都使用到了 1.1 异步写入 const fs require("fs");// 写入文件 fs.writeFile(./sentence.txt, "Hello world", e…

数据结构复习 (顺序查找,对半查找,斐波那契查找,插值查找,分块查找)

查找&#xff08;检索&#xff09;&#xff1a; 定义&#xff1a;从给定的数据中找到对应的K 1&#xff0c;顺序查找&#xff1a; O(n)的从前向后的遍历 2&#xff0c;对半查找&#xff0c;要求有序 从中间开始查找&#xff0c;每次检查中间的是否正确&#xff0c;不正确就…

kafka使用以及基于zookeeper集群搭建集群环境

一、环境介绍 zookeeper下载地址&#xff1a;https://zookeeper.apache.org/releases.html kafka下载地址&#xff1a;https://kafka.apache.org/downloads 192.168.142.129 apache-zookeeper-3.8.4-bin.tar.gz kafka_2.13-3.6.0.tgz 192.168.142.130 apache-zookee…

Redis的内存预分配策略

Redis的内存预分配策略是一种优化手段&#xff0c;旨在减少频繁的内存分配和释放操作对性能的影响。以下是对Redis在使用各数据结构类型时内存变化以及触发底层数据结构变化条件的详细分析&#xff1a; 一、内存预分配策略概述 Redis通过预先分配足够的内存&#xff0c;可以提高…

卸载wps后word图标没有变成白纸恢复

这几天下载了个wps教育版&#xff0c;后头用完了删了 用习惯的2019图标 给兄弟我干没了&#xff1f;&#xff1f;&#xff1f; 其他老哥说什么卸载关联重新下 &#xff0c;而且还要什么撤销保存原来的备份什么&#xff0c;兄弟也是不得不怂了 后头就发现了这个半宝藏博主&…

麒麟服务器安装kafka--亲测

我这安装的是单机版本的&#xff1a; 下载地址&#xff1a;Index of /kafka/3.9.0 我下载的是&#xff1a;https://dlcdn.apache.org/zookeeper/zookeeper-3.9.3/apache-zookeeper-3.9.3-bin.tar.gz https://dlcdn.apache.org/kafka/3.9.0/kafka_2.12-3.9.0.tgz 一、下载并上…

104周六复盘 (188)UI

1、早上继续看二手书的一个章节&#xff0c;程序开发流程、引擎、AI等内容&#xff0c; 内容很浅&#xff0c;基本上没啥用&#xff0c;算是复习。 最大感触就是N年前看同类书的里程碑、AI相关章节时&#xff0c;会感觉跟自己没啥关系&#xff0c; 而如今则密切相关&#xf…

Chromebook 的 4 个最佳变声器

您对使用chromebook 变声器感到困惑吗&#xff1f;您是否认为在 Chromebook 上安装变声器很困难&#xff1f;如果是&#xff0c;那么这篇文章适合您&#xff0c;因为在 Chromebook 上安装和使用简单且准确的变声器非常简单且轻松。 在本文中&#xff0c;我们将分享适用于 Chro…

DC系列之DC-8渗透测试

DC-8 靶机渗透测试实战 靶机下载地址&#xff1a; https://download.vulnhub.com/dc/DC-8.zip&#xff08;下载速度慢可以用迅雷下载&#xff09; 一、实验环境 实验环境&#xff1a; kali2024&#xff1a;192.168.234.145&#xff08;nat模式&#xff09; 靶机环境DC-7&#…

12306分流抢票软件 bypass v1.16.43 绿色版(春节自动抢票工具)

软件介绍 12306Bypass分流抢票软件&#xff0c;易操作强大的12306抢票软件&#xff0c;全程自动抢票&#xff0c;云识别验证码打码&#xff0c;多线程秒单、稳定捡漏&#xff0c;支持抢候补票、抢到票自动付款&#xff0c;支持多天、多车次、多席别、多乘客、短信提醒等功能。…

NS4861 单灯指示独立耳锂电池充放电管理 IC

1 特性  最大 500mA 线性充电电流&#xff0c;外部可调节  内部预设 4.2V 充电浮充电压  支持 0V 电池充电激活  支持充满 / 再充功能  内置同步升压放电模块&#xff0c;输出电压 5.1V  同步升压 VOUT 最大输出电流 500mA  VOL/OR 独…