AcWing 840. 模拟散列表(C++算法)

AcWing 840. 模拟散列表

1、题目:
维护一个集合,支持如下几种操作:

“I x”,插入一个数x;
“Q x”,询问数x是否在集合中出现过;
现在要进行N次操作,对于每个询问操作输出对应的结果。

输入格式
第一行包含整数N,表示操作数量。

接下来N行,每行包含一个操作指令,操作指令为”I x”,”Q x”中的一种。

输出格式
对于每个询问指令“Q x”,输出一个询问结果,如果x在集合中出现过,则输出“Yes”,否则输出“No”。

每个结果占一行。

数据范围
1≤N≤105
−109≤x≤109

输入样例:
5
I 1
I 2
I 3
Q 2
Q 5
输出样例:
Yes
No

2、基本思想:
取一个标准值,用待插入或者待查找的数模上这个标准值。
法一:拉链法:
①标准值的选择:就是大于N的最小质数;

	for (int i = 100000; ; i ++ )
	{
		bool flag = true;
		for (int j = 2; j * j <= i; j ++ )
		{
			if (i % j == 0)
			{
				flag = false;
				break;
			}
		}
		if (flag) 
		{
			cout << i;
			break;
		}
	}

②h[N]代表了不同的槽,每一个槽按照头插法拉链。
AcWing 840. 模拟散列表(C++算法)_第1张图片
法二:开放寻址法:
①标准值的选择:取大于2N或3N的最小质数;

	for (int i = 200000; ; i ++ )
	{
		bool flag = true;
		for (int j = 2; j * j <= i; j ++ )
		{
			if (i % j == 0)
			{
				flag = false;
				break;
			}
		}
		if (flag) 
		{
			cout << i;
			break;
		}
	}

②取一个大于109的null;
③h[N]代表不同的槽,如果访问的槽中数据不等于null则访问下一个槽,直到顺利放入槽中为止。

3、C ++ 代码如下(该代码引用AcWing网站代码)
法一:

#include 
#include 

using namespace std;

const int N = 100003;

int h[N], e[N], ne[N], idx, x;
char op[2];

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

bool find(int x)
{
     
    int t = (x % N + N) % N;
    for (int i = h[t]; i != -1; i = ne[i])
    {
     
        if (e[i] == x) return true;
    }
    return false;
}
int main()
{
     
    memset(h, -1, sizeof h);
    
    int n;
    cin >> n;
    
    while (n -- )
    {
     
        cin >> op >> x;
        if (!strcmp(op, "I")) insert(x);
        else
        {
     
            if (find(x)) cout << "Yes" << endl;
            else cout << "No" << endl;
        }
    }
    return 0;
}//该代码引用AcWing网站代码

法二:

#include 
#include 

using namespace std;

const int N = 200003, null = 0x3f3f3f3f;

int h[N], x;
char op[2];

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

int main()
{
     
    memset(h, 0x3f, sizeof h);
    
    int n;
    cin >> n;
    
    while (n -- )
    {
     
        cin >> op >> x;
        if (!strcmp(op, "I")) h[find(x)] = x;
        else
        {
     
            if (h[find(x)] == null) cout << "No" << endl;
            else cout << "Yes" << endl;
        }
    }
    return 0;
}//该代码引用AcWing网站代码

注意事项:
①memset(h, -1, sizeof h);是把h[N]数组中每个元素初始化为-1。-1在计算机中以补码形式存在就是32个1(11…1)后八位是11111111,就会将h[N]数组中每个元素每个字节赋成11111111,四个11111111转换成十进制还是-1。
memset(h, 0x3f, sizeof h);是把h[N]数组中每个元素初始化为0x3f3f3f3f(因为h是int型是4个字节,)。0x3f3f3f3f是ACM中常用的无穷大常量。
②(x % N + N) % N是为了将负数取的模变成正数,便于与该负数相反数取模的数区分。

你可能感兴趣的:(哈希表,c++,算法)