• [C++]实现散列表的分离链接法的数据结构


      散列表,英文叫做Hash Table,因此也叫哈希表,是一种根据关键字值来确定主存中存储位置的数据结构.通过一个散列函数(关于键值的函数),来确定存储该关键字的位置.

      主要的方法有:  1.分离链接法(拉链法)

      分离链接法的散列函数为 position = key % n. 即关键字的存储位置为关键字的值对表项的数量取模.若表项大小为13,对于关键值为27的项,存储在1(27 % 13 = 1)的表项处.为了减少冲突,n往往取素数.对于同余的关键字,采用 队列(链表) 的方式连接在一起,新放入的元素放入队头或者队尾均可.用图描述如下:

      2.线性探查法

        线性探查法是根据冲突次数,来从目标位置后移冲突次数次位置来避免冲突的,即position_new = (position + i) % n,其中i为冲突次数,n为表项大小.

      3.平方探查法

        与线性探查法类似,只不过是散列函数的不同,其position_new = (position + i) % n

      4. 双散列,再散列等

     

      分离链接法的数据结构的数据结构的构造,使用一个名为HashTable的类来封装整个表的操作和属性.用vector<deque<int>>来表示整个数据结构,即整个表是一个由(双端)

    队列组成的向量(数组).类中还包含其他的函数,用来访问类中的私有属性.

      类的声明如下:

     1 class HashTable {
     2     public:
     3         HashTable(int = 11);
     4         ~HashTable() = default;
     5         int getHashItemSize(const int) const;        //获得队列长度
     6         int getHashTableSize() const;        //获得表项的大小
     7         bool insertRecord(int);        //插入一个值
     8         void removeRecord(const int);            //删除一个值
     9         bool isEmpty() const;       //判断哈希表是否为空
    10         void print() const;       //打印哈希表
    11 
    12     private:
    13         vector<deque<int>>  HashItem;    //结构定义
    14         int HashTableSize = 0;      //哈希表表项数
    15 };

      

    构造函数定义:

      

     1 HashTable::HashTable(int n)     //构造函数定义
     2 {
     3     HashTableSize = n;
     4 
     5     for (int i = 0; i < n; ++i)
     6     {
     7         deque<int> adeque;
     8         HashItem.push_back(adeque);     //向向量中压入足够的空队列
     9     }
    10 }

    插入记录的函数的定义:

     1 bool HashTable::insertRecord(int data)      //插入一个指定值的记录
     2 {
     3     int position = data % HashTableSize;                //映射规则
     4 
     5     if (position >= HashTableSize || position < 0)    //合法性判断
     6         return false;
     7 
     8     else
     9     {
    10         HashItem.at(position).push_front(data);  //根据时间局部性原理,插入到队头
    11         return true;
    12     }
    13 }

     

    删除记录的函数定义

     1 void HashTable::removeRecord(const int aim)     //删除一个指定值的记录
     2 {
     3     int i = 0;
     4     int j = 0;
     5 
     6     for (; i < HashTableSize; ++i)            //遍历表项
     7     {
     8 
     9         for (j = 0; j < static_cast<int>(HashItem.at(i).size()); ++j)                //遍历队列
    10         {
    11             if (HashItem.at(i).at(j) == aim)
    12                 HashItem.at(i).erase(HashItem.at(i).begin() + j);       //删除记录
    13         }
    14     }
    15 
    16 }

    打印函数:

     1 void HashTable::print() const
     2 {
     3     for (int i = 0; i < getHashTableSize(); ++i)        //遍历表项
     4     {
     5         deque<int> temp = HashItem.at(i);
     6 
     7         for (auto &j : temp)            //遍历队列
     8             cout << j << ' ';
     9 
    10         cout << endl;
    11     }
    12 }

    对于主函数,写了一点测试语句来进行测试:

     1 int main()
     2 {
     3     HashTable hashtable(13);
     4 
     5     for (int i = 0; i < 100; ++i)
     6         hashtable.insertRecord(i);
     7 
     8     hashtable.print();
     9 
    10     cout << endl;
    11 
    12     hashtable.removeRecord(91);
    13     hashtable.removeRecord(70);
    14 
    15     hashtable.print();
    16 
    17     return 0;
    18 }

    插入0到99的关键字,散列到表项大小为13的散列表中,在删除91和70两个关键值.

    运行结果输出了0到99的散列情况和删除操作之后的散列情况:

    本人原创,转载请注明出处,谢谢合作!

  • 相关阅读:
    nacos+Seata+Mybatis plus 教程
    快速排序 #java实现
    高内聚,低耦合
    整合Alibaba Sentinel 教程
    执行 aptget update 时错误 由于没有公钥,无法验证下列签名: NO_PUBKEY F76221572C52609D
    上飞机https://zhuzhu12.xyz/link/8YFX1tSR3sy3Wj2S?clash=1
    Ubuntu安装MongoDB
    指针为什么有数据类型?
    很强!Mybatis plus 学习教程 “手写SQL配置” “Mapper多参数传参” + 坑点说明
    自动清理内存 #最强,让电脑不卡的神器#最有用
  • 原文地址:https://www.cnblogs.com/Agent-YRBlogs/p/6082362.html
Copyright © 2020-2023  润新知