C++数据结构之哈希表的实现

以下是详细的讲解:

C++数据结构之哈希表的实现

哈希表的概念

哈希表是一种能够实现快速查找的散列表,通过将关键字映射到哈希表中的一个位置来实现快速查找。哈希表的查询、删除时间复杂度为O(1),操作效率非常高,所以常常被用来对大量数据进行检索。

哈希表的实现

哈希函数

哈希函数的主要作用就是将任意长度的输入数据转化为固定长度的散列值,一般采用对关键字进行取模的方式,也可以使用其他算法。哈希函数的设计对哈希表的性能有着至关重要的作用。

例如,下面是一个简单的哈希函数实现:

int hashFunc(int key, int tableSize){
    return key % tableSize;
}

其中,key是关键字,tableSize是哈希表的大小,hashFunc函数将key值取模作为哈希值返回。

冲突解决

当不同的关键字映射到同一个哈希值时,就发生了冲突。哈希表的冲突解决方法有很多种,这里介绍两种比较常用的方法。

链表法

链表法是一种将冲突的关键字以链表的形式串联起来,存放到同一个哈希值对应的位置上。

例如,以下是一个简单的链表法哈希表实现:

struct Node{
    int key;
    Node* next;
    Node(int k) : key(k), next(nullptr) {}
};

class HashTable{
private:
    int tableSize;
    vector<Node*> hashTable;
    int hashFunc(int key){
        return key % tableSize;
    }
public:
    HashTable(int size){
        tableSize = size;
        hashTable.resize(tableSize);
    }

    void insert(int key){
        int hashValue = hashFunc(key);
        if(hashTable[hashValue] == nullptr){
            hashTable[hashValue] = new Node(key);
        } else {
            Node* currentNode = hashTable[hashValue];
            while(currentNode->next != nullptr){
                currentNode = currentNode->next;
            }
            currentNode->next = new Node(key);
        }
    }

    bool search(int key){
        int hashValue = hashFunc(key);
        Node* currentNode = hashTable[hashValue];
        while(currentNode != nullptr){
            if(currentNode->key == key){
                return true;
            }
            currentNode = currentNode->next;
        }
        return false;
    }

    void remove(int key){
        int hashValue = hashFunc(key);
        Node* currentNode = hashTable[hashValue];
        Node* prevNode = nullptr;
        while(currentNode != nullptr){
            if(currentNode->key == key){
                if(prevNode == nullptr){
                    hashTable[hashValue] = currentNode->next;
                } else {
                    prevNode->next = currentNode->next;
                }
                delete currentNode;
                return;
            }
            prevNode = currentNode;
            currentNode = currentNode->next;
        }
        return;
    }
};

在上面的实现中,我们将哈希值相同的关键字以链表的形式进行存储,这样,在查找关键字的时候,如果哈希值相同,我们就沿着链表依次查找,直到找到目标位置或者链表遍历完毕。

开放定址法

开放定址法是一种将冲突的关键字插入到哈希表中空闲的地址上,常见的几种方式有线性探测、二次探测和双重散列等。

例如,以下是一个简单的线性探测哈希表实现:

class HashTable{
private:
    int tableSize;
    vector<int> hashTable;
    int hashFunc(int key){
        return key % tableSize;
    }
public:
    HashTable(int size){
        tableSize = size;
        hashTable.resize(tableSize, -1);
    }

    void insert(int key){
        int hashValue = hashFunc(key);
        int i = 0;
        while(hashTable[(hashValue + i) % tableSize] != -1){
            i++;
        }
        hashTable[(hashValue + i) % tableSize] = key;
    }

    bool search(int key){
        int hashValue = hashFunc(key);
        int i = 0;
        while(hashTable[(hashValue + i) % tableSize] != key && hashTable[(hashValue + i) % tableSize] != -1){
            i++;
        }
        if(hashTable[(hashValue + i) % tableSize] == key){
            return true;
        } else {
            return false;
        }
    }

    void remove(int key){
        int hashValue = hashFunc(key);
        int i = 0;
        while(hashTable[(hashValue + i) % tableSize] != key && hashTable[(hashValue + i) % tableSize] != -1){
            i++;
        }
        if(hashTable[(hashValue + i) % tableSize] == key){
            hashTable[(hashValue + i) % tableSize] = -1;
        }
        return;
    }
};

在上面的实现中,我们使用线性探测的方式解决了冲突问题,具体来说,在插入关键字的时候,如果目标位置已经有了其他关键字,我们就把目标位置后继的位置再判断一遍,直到找到一个空闲的地址,然后将关键字插入到该位置。在查找和删除时,我们同样需要进行连续的查找操作直到查找到目标位置或者发现该位置已经被占用了。

示例说明

链表法哈希表

以下是一个简单的用链表法实现的哈希表示例:

HashTable hashTable(10);
hashTable.insert(1);
hashTable.insert(12);
hashTable.insert(23);
hashTable.insert(14);
hashTable.insert(35);

cout << hashTable.search(12) << endl;
cout << hashTable.search(18) << endl;

hashTable.remove(14);

cout << hashTable.search(14) << endl;

运行结果如下:

1
0
0

在上面的示例中,我们首先创建了一个哈希表,然后插入了5个不同的关键字。然后我们分别查找哈希表中是否包含12和18这两个关键字,最后删除14这个关键字,然后再次检查哈希表中是否包含14这个关键字。可以看到,我们使用链表法实现的哈希表能够正常地进行插入、查找、删除操作,并且在删除关键字后,能够正确地返回“false”。

开放定址法哈希表

以下是一个简单的用开放定址法实现的哈希表示例:

HashTable hashTable(10);
hashTable.insert(1);
hashTable.insert(12);
hashTable.insert(23);
hashTable.insert(14);
hashTable.insert(35);

cout << hashTable.search(12) << endl;
cout << hashTable.search(18) << endl;

hashTable.remove(14);

cout << hashTable.search(14) << endl;

运行结果如下:

1
0
0

在上面的示例中,我们同样首先创建了一个哈希表,然后插入了5个不同的关键字。然后我们同样分别查找哈希表中是否包含12和18这两个关键字,最后删除14这个关键字,然后再次检查哈希表中是否包含14这个关键字。可以看到,我们使用开放定址法实现的哈希表同样能够正常地进行插入、查找、删除操作,并且在删除关键字后,能够正确地返回“false”。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:C++数据结构之哈希表的实现 - Python技术站

(0)
上一篇 2023年5月17日
下一篇 2023年5月17日

相关文章

  • 牛客小白月赛71

    A.猫猫与广告 题目: 分析: 只需考虑c * d的矩阵竖着摆和横着摆两种情况。本题提示了考虑两矩阵对应边平行的情况,实际上可以证明倘若能斜着放,那么一定可以横着放或竖着放,证明方式可已通过构造三角形来证明a* b的矩阵的长宽一定小于c * d矩阵的长宽。 code: #include <iostream> #include <cmath&…

    算法与数据结构 2023年4月25日
    00
  • JS中的算法与数据结构之二叉查找树(Binary Sort Tree)实例详解

    JS中的算法与数据结构:二叉查找树(Binary Sort Tree) 什么是二叉查找树 二叉查找树(Binary Sort Tree),又称二叉搜索树或二叉排序树,是一种特殊的二叉树结构。它具有以下性质: 每个结点最多只有两个子结点。 左子树中的所有结点的值均小于它的根结点的值。 右子树中的所有结点的值均大于它的根结点的值。 没有相同节点值出现 因为具备以…

    数据结构 2023年5月17日
    00
  • 带你了解Java数据结构和算法之哈希表

    带你了解Java数据结构和算法之哈希表 前言 哈希表是一种常用的数据结构,它可以高效地存储和查询数据。在计算机科学领域,哈希表广泛用于实现关联数组(Associative Array)和哈希集合(Hash Set)。本文将带领大家深入了解哈希表数据结构及常用算法实现。 哈希表的原理 哈希表是根据关键码值(Key Value)而直接进行访问的数据结构。也就是说…

    数据结构 2023年5月17日
    00
  • 如何配置git环境

    首先我们新建一个文件夹;    然后我们右键git Bash Here一下;在里面输入: cd ssh-keygen cd.ssh ls (注意,我们要是之前就生成过密钥,直接输入ls就好了) 输入ls之后,会显示出来我们的公钥,我们输入: cat id_rsa.pub 然后密钥就出来了,密钥出来之后,我们把密钥复制一下,打开github 选择设置; 中会有…

    算法与数据结构 2023年4月18日
    00
  • C语言数据结构时间复杂度及空间复杂度简要分析

    C语言数据结构时间复杂度及空间复杂度简要分析 什么是时间复杂度和空间复杂度? 在分析算法和数据结构的性能时,时间复杂度和空间复杂度是必须考虑的因素。 时间复杂度:衡量算法执行时间所需的资源,也就是算法的速度。通常使用“大O符号”来表示时间复杂度,例如O(1)、O(n)、O(nlogn)等。 空间复杂度:衡量算法使用的内存资源,也就是算法的空间利用率。通常使用…

    数据结构 2023年5月17日
    00
  • oracle 数据库学习 基本结构介绍

    Oracle 数据库学习:基本结构介绍攻略 概述 Oracle 数据库是目前世界上使用最为广泛的一种关系型数据库。学习 Oracle 数据库需要具备一定的数据库基础知识,特别是SQL语言的使用,才能更好地理解 Oracle 数据库的基本结构。本攻略将从以下几个方面介绍 Oracle 数据库的基本结构: 数据库系统组成; Oracle 实例; 数据库; 表空间…

    数据结构 2023年5月17日
    00
  • python数据结构之二叉树的统计与转换实例

    下面是针对“python数据结构之二叉树的统计与转换实例”的详细讲解攻略: 什么是二叉树 二叉树指的是一种树状结构,具有如下特点: 每个节点最多有两个子节点,分别为左子节点和右子节点 左子节点的值比父节点小,右子节点的值比父节点大 二叉树可以是空树,也可以是非空树。 二叉树的遍历 在对二叉树进行操作时,需要对其节点进行遍历。二叉树的遍历方式一般有以下三种: …

    数据结构 2023年5月17日
    00
  • LCA——ST表+欧拉序

    了解到一个quan新的东西: 用ST表(欧拉序)实现LCA(树上最近公共祖先) 欧拉序 前序遍历得到的序列,叫dfs序但数字可以重复出现,一进一出,叫欧拉序会发现根结点总在中间而根结点是该段序列深度最小的点因此两个点的LCA,就是在该序列上两个点第一次出现的区间内深度最小的那个点 即转化为区间RMQ问题,可以用ST表当然你可以再写一棵线段树(如果有修改操作)…

    算法与数据结构 2023年5月4日
    00
合作推广
合作推广
分享本页
返回顶部