首页 > 其他分享 >考研数据结构——每日一题[哈希表]

考研数据结构——每日一题[哈希表]

时间:2023-08-14 14:04:03浏览次数:37  
标签:include return idx int 考研 哈希 数据结构 find op

840. 模拟散列表

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

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

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

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

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

每个结果占一行。

数据范围 1≤N≤10^5^ −10^9^≤x≤10^9^ 输入样例: 5 I 1 I 2 I 3 Q 2 Q 5 输出样例: Yes No

闭散列方法(开放寻址法):





#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200003, null = 0x3f3f3f3f;

int n;
int h[N];

int find(int x) //开发寻址法查找
{
    int t = (x % N + N) % N;
    while (h[t] != null && h[t] != x) //不为空且值相等
        t = (t + 1) % N;
    return t;//找不到x值,最终落在未赋值的null = 0x3f3f3f3f
}

int main()
{
    memset(h, 0x3f, sizeof h);//开发寻址法,初始最大值,null定义为0x3f3f3f3f
    scanf("%d", &n);
    while (n -- )
    {
        char op[2];
        int x;
        scanf("%s%d", op, &x);   //'*'取字符串单个字符(bushi),直接op打出全部内容 
        if (*op == 'I') h[find(x)] = x;//find找到位置且赋值  
        else
        {
            if (h[find(x)] == null) puts("No");
            else puts("Yes");
        }
    }

    return 0;
}



开散列方法(拉链法):

数组模拟链表+find函数-->insert函数 int t = (x % N + N) % N ; //负数整数都转化成为正数【c++取模负数仍为负数】

深度解析数组模拟链表: e数组存放每个idx下标值, ne数组存放每个下标指向的下一个下标,add中指向 h数组仅存放最后添加的节点下标【当做每个下标为链表的初始起点】


#include <iostream>
#include <cstring>
#include <algorithm>

using namespace std;

const int N = 200003;//除余法需要先找离N最大范围最近的质数【试除法,口算也行】

int n;
int h[N], e[N], ne[N], idx;

bool find(int x)//查找t=x的hash值映射的h[t]单链表是否存在x
{
    int t = (x % N + N) % N;//除余法
    for (int i = h[t]; ~i; i = ne[i])//遍历映射hash值t所在h[t]是否存在x,~i等效 i != -1
        if (e[i] == x)
            return true;
    return false;
}

void add(int a,int b )//链表头插法  : 添加一条边 a->b 
{
	e[idx] =  b , ne[idx] = h[a] , h[a] = idx ++;
}

void insert(int x)
{
	if(find(x)) return ;
	int t = (x % N  + N) % N ; //负数整数都转化成为正数【c++取模负数仍为负数】
	add(t,x);
}
int main()
{
	memset(h , -1 , sizeof h);//二进制全为1  ,遍历邻接表 i = h[t]; ~i 按位取反二进制每位全部为0
	scanf("%d",&n);
	while(n --)
	{
		char op[2];
		int x;
		scanf("%s%d",op,&x);
		if(*op == 'I' ) insert(x);//*取字符串单个字符(bushi),直接op打出全部内容
		else 
		{
			if(find(x)) puts("Yes");
			else puts("No");
		}
	}
	return 0;
}

标签:include,return,idx,int,考研,哈希,数据结构,find,op
From: https://blog.51cto.com/u_15623277/7076062

相关文章

  • Redis设计与实现——数据结构(二刷)
    SDS动态字符串Redis是c语言实现的,传统c字符串存在不可变导致的频繁内存分配,一些API函数可能引起缓冲区溢出等问题。Redis在c字符串的基础上,封装实现了SDS动态字符串,能够根据每次存储关键字的大小自动申请额外缓冲区内存,避免频繁申请和缓冲区溢出问题。SDS定义str......
  • 数据结构与算法 --- 如何分析排序算法
    引言排序算法是最基础的算法,对于排序算法,除学习算法原理,代码实现之外,更重要的是学习每个算法的特点,知道在什么场景下选择那种算法。那一定是选择时间复杂度最低的排序算法就是最优的吗?可以从以下几个方面分析一下。排序算法的执行效率对于排序算法的执行效率,一般从以下几个方......
  • 考研线代:拉格朗日配方法怎么用?一篇文章就搞明白!
    考研线代:拉格朗日配方法怎么用?一篇文章就搞明白:https://zhaokaifeng.com/16687/......
  • 数据结构与算法 --- 组数、链表、栈和队列(一)
    数组、链表、栈和队列是四种基础数据结构,他们是高级、复杂的数据结构和算法的基础。本篇先来讲述数组,链表,及算法的优化策略。数组定义数组:数组是一种线性表数据结构,它用一组连续的内存空间存储一组具有相同类型的数据。定义中有三个关键词:线性表连续的内存空间相同类型数......
  • 数据结构与算法 --- “哨兵”思想
    引言哨兵思想是指在算法中使用一个特殊值来检测或标记某些条件的发生,它的目的是为了简化代码,并使其更容易理解,常常用于在循环中优化边界条件的判断。介绍在算法中,"哨兵"思想是指在循环中设置一个特殊的元素(称为哨兵),以便在循环过程中能够更高效地处理某些边界情况或结束条件。......
  • 数据结构与算法 --- 组数、链表、栈和队列(二)
    继数据结构与算法---组数、链表、栈和队列(一)讲解完数组,链表及算法的优化策略之后,接下来继续讲解两种特殊的线性表结构,栈和队列。栈对“栈”有一个很形象的比喻,栈就像一摞叠在一起的盘子,放盘子时,只能放在上面,不能将盘子插入到中间的任意位置;取盘子时,只能从最上面取,不能从中间任......
  • 数据结构与算法 --- 排序算法(一)
    引言按照时间复杂度,将一些常见排序算法进行分类,分为以下三类:\(O(n^2)\):冒泡排序,插入排序,选择排序。\(O(nlogn)\):快速排序,归并排序。\(O(n)\):桶排序,计数排序,基数排序。本篇文章讨论以下第一类:冒泡排序,插入排序,选择排序。上一篇数据结构与算法---如何分析排序算法提......
  • 数据结构与算法 --- 递归(二)
    引言上文数据结构与算法---递归(一)讲述了什么是递归算法,如何编写递归算法及如何写好递归算法,本文着重讲述一下如何避免递归过深导致的堆栈溢出问题。探究产生堆栈溢出的原因函数调用采用函数调用栈来保存当前“快照”(局部变量,返回地址等)。函数调用栈是内存中开辟的一块存储空......
  • 数据结构与算法 --- 递归(一)
    什么是递归?递归(Recursion)是一种解决问题的方法,它将问题分解为更小的子问题,并逐层解决这些子问题。递归算法的核心思想是:一个函数可以直接或间接地调用自身。通过这种自我调用,我们可以用简洁的代码来解决复杂问题。满足递归的条件一般来说,满足下面三个条件就可以使用递归:待......
  • 数据结构与算法 --- 排序算法(二)
    title:数据结构与算法---排序算法(二)category:数据结构与算法tags:算法updatedAt:2023-05-18T15:29:17.847ZcreatedAt:2023-05-13T14:43:31.656Z引言上一篇数据结构与算法---排序算法(一)中,学习了冒泡排序,插入排序,选择排序这三种时间复杂度为\(O(n^2)\)的算法。实......