gwl999

博客园 首页 新随笔 联系 订阅 管理
  34 随笔 :: 0 文章 :: 0 评论 :: 2067 阅读

5.21

哈希表


Hash表又称为散列表,一般由Hash函数(散列函数)与链表结构共同实现,与离散化思想类似。

一般要求:防止冲突,便于查询

模拟hash表:

  • 拉链法:两个核心操作insert(),find();

    • int h[N], e[N], ne[N], idx; //邻接表进行存储;

    •  

       

    • void insert(int x) {
          // c++中如果是负数 那他取模也是负的 所以 加N 再 %N 就一定是一个正数
          int k = (x % N + N) % N;
          //hash防冲突取值
          e[idx] = x;
          //赋值
          ne[idx] = h[k];
          //h[k]是一个拉链的结点,例如2下面的拉链;
          h[k] = idx++;
          //通过拉链进行延申
      }
    • bool find(int x) {
          //用上面同样的 Hash函数 讲x映射到 从 0-1e5 之间的数
          int k = (x % N + N) % N;
          for (int i = h[k]; i != -1; i = ne[i]) {
          //经典的邻链表的遍历操作;
              if (e[i] == x) {
                  return true;
          //能找到
              }
          }
          return false;
      }

例题链接:https://www.acwing.com/problem/content/842/


  • #include "cstring"
    #include "iostream"
    using namespace std;
    const int N = 100003;
    int h[N], e[N], ne[N], idx;
    void insert(int x) {
        int t = (x % N + N) % N;
        e[idx] = x;
        ne[idx] = h[k];
        h[k] = idx++;
    }
    bool find(int x) {
        int k = (x % N + N) % N;
        for (int i = h[k]; i != -1; i = ne[i]) {
            if (e[i] == x)
                return true;
        }
        return false;
    }
    int main() {
        // for (int i = 100000; i; i++) {
        //     bool flag = true;
        //     for (int j = 2; j * j < i; j++) {
        //         if (i % j == 0) {
        //             flag = false;
        //             break;
        //         }
        //     }
        //     if (flag) {
        //         cout << i;
        //         break;
        //     }
        // }
        //这里是找到N的操作,一般是取质数为hash计算的最好办法
        memset(h, -1, sizeof h);
        //将槽先清空 空指针一般用 -1 来表示
        int m;
        cin >> m;
        while (m--) {
            char op;
            int x;
            cin >> op >> x;
            if (op == 'I') {
                insert(x);
    
            } else {
                if (find(x))
                    cout << "Yes" << endl;
                else
                    cout << "No" << endl;
            }
        }
        return 0;
    }0;
    }< "No" << endl;
            }
        }
        return 0;
    }

  • 开放寻址法(推荐):

  • 其实就是开辟两到三倍的一维数组空间大小来存放原来的数值;

  • 主要方法:find(int x)找到x;两种结果

    • 如果能找到,就返回x的下标,同时也对应着query操作

    • 如果不能找到,那么返回x需要被插入的位置,对应着insert的操作;

  • #include "cstring"
    #include "iostream"
    using namespace std;
    const int N = 200003, null = 0x3f3f3f3f;
    int h[N];
    int find(int x) {
        //找一个数是否存在,结果两种:一是存在的话,就返回它的位置,如果不存在,那么就需要返回它被插入的位置;
        int k = (x % N + N) % N;
        //散列原数,同时也找到x的位置
        while (h[k] != null && h[k] != x) {
            //如果k位置的元素是空要么k位置的元素就是x的位置,那么就不需要判断,直接返回k就是要找的位置
            k++;
            //如果当前位置被人家占了,就往后挪,直到N数组总长。总长都不够就从头开始
            if (k == N)
                k = 0;
        }
        return k;
    }
    int main() {
        int m;
        cin >> m;
        memset(h, 0x3f, sizeof h);
        //对所有元素初始化为null配合h[k]!=null的查找
        while (m--) {
            char op;
            int x;
            cin >> op >> x;
            int k = find(x);
            if (op == 'I')
                h[k] = x;
            //直接将k的位置给x元素就行
            else {
                if (h[k] != null)
                    //说明存在元素;
                    cout << "Yes" << endl;
                else
                    cout << "No" << endl;
            }
        }
        return 0;
    }
posted on   呓雫  阅读(37)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· DeepSeek 开源周回顾「GitHub 热点速览」
· 记一次.NET内存居高不下排查解决与启示
· 物流快递公司核心技术能力-地址解析分单基础技术分享
· .NET 10首个预览版发布:重大改进与新特性概览!
· .NET10 - 预览版1新功能体验(一)
点击右上角即可分享
微信分享提示