Hash表_拉链法_开放寻址法_模拟散列表

文章目录

  • Hash表
    • 作用
    • ① 拉链法
    • ② 开放寻址法
    • 例 - 模拟散列表
      • > 拉链法
      • > 开放寻址法

Hash表

一般只有添加、查找

(注意:离散化为特殊的哈希方式,因为离散化需要提前保序)

作用

将一堆数据 通过hash函数映射为 0 ~ N的数

hash函数:x mod N(N一般取质数)

当不同的数映射成一个数时,产生冲突,处理冲突有两种方法。

① 拉链法

(存放下标的数组h初始化为-1)
Hash表_拉链法_开放寻址法_模拟散列表_第1张图片

插入

void insert(int x)
{
    int k = (x % N + N) % N;
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx ++;
}

注意 :求其余数时,值可正可负(-10 % 3 == -1),需要保证为正数

%N + N ) % N,不可 + N ) % N ,x在-1e+09 ~ 1e+09,N为 10^5,这样无法保证k为正数

查找

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;
} 

② 开放寻址法

当映射时,若该位已有数,则继续向后查找,直至找到空位,存下。

(数组存放的是数值,初始化为无穷大即可,规定一个值 null)
Hash表_拉链法_开放寻址法_模拟散列表_第2张图片

//若x存在返回其位置,若x不存在返回其应该在的位置。
int find(int x)
{
    int k = (x % N + N) % N;
    while(h[k] != null && h[k] != x)
    {
        k++;
        if(k = N) k = 0;    //k到最后一个,则从头循环
    }
    return k;
}
  • h[k] == x 时:说明已存在x,返回其位置即可。

  • h[k] == null 时:说明不存在x,返回其应该在的位置。注意后续需要将x填入。

例 - 模拟散列表

Hash表_拉链法_开放寻址法_模拟散列表_第3张图片

> 拉链法

#include 
#include 
using namespace std;

const int N = 200003;
int h[N];

void insert(int x)
{
    int k = (x % N + N) % N;
    e[idx] = x;
    ne[idx] = h[k];
    h[k] = idx;
    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()
{
    memset(h,-1,sizeof h );
    int n,x;
    scanf("%d",&n);
    char op[2];
    while(n--)
    {
        scanf("%s",op);
        if(op[0] == 'I')
        {
            scanf("%d",&x);
            insert(x);
        }
        else
        {
            scanf("%d",&x);
            if(!find(x)) puts("No");
            else puts("Yes");
        }
    }
    return 0;
}

> 开放寻址法

#include 
#include 
using namespace std;

const int N = 200003;
const int null = 0x3f3f3f3f;
int h[N];


int find(int x)
{
    int k = (x % N + N) % N;
    while(h[k] != null && h[k] != x)
    {
        k++;
        if(k == N) k = 0;
    }
    return k;
}


int main()
{
    memset(h,0x3f,sizeof h );
    int n,x;
    scanf("%d",&n);
    char op[2];
    while(n--)
    {
        scanf("%s",op);
        if(op[0] == 'I')
        {
            scanf("%d",&x);
            h[find(x)] = x;
        }
        else
        {
            scanf("%d",&x);
            if(h[find(x)] == null) puts("No");
            else puts("Yes");
        }
    }
    return 0;
}

注意:

以上两种方法h[k]代表的含义不同

拉链法:映射到k的数的下标 idx

开放寻址法:映射到k的数(k可能为负数,数组初始化时)

你可能感兴趣的:(算法入门,c++,算法,数据结构)