哈希的一种用法——判断相等

本文介绍如何在数据量大、时间限制严苛的情况下利用哈希表进行高效数据处理。通过构造哈希表并使用特定哈希函数,实现快速判断数据是否重复。适用于如POJ竞赛等问题解决。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

小结来源:poj3349 & poj3274


在输入数据量比较大,时间要求比较高的情况下,判断相等可以考虑哈希的方法,比如,输入10W、100W,时间要求4000MS、7000MS,用普通方法肯定要TLE的,这时就需要hash。


首先要构造hash表,这里根据输入量来确定hash table的大小,比如poj3349中输入量最大12W,所以最坏情况每一种雪花都不相等需要12W个哈希项,所以这里设置HASH_BASE=12W以上的最小素数=120007(后面hash函数使用直接取余法)。

这里的构造相对简单,每次插入一个数据,这个数据都看成一个HashNode,并且用cur标记它是第几个HashNode。HashNode除了要有指向下一个HashNode的next指针外(如果两个HashNode哈希值相同,则映射到hash table的同一个地址处),还要有判断两个HashNode是否相等的变量,这里认为如果两个HashNode的num数组相等,就认为两个HashNode是同一片雪花。

const int HASH_BASE = 1200007;//100000*12以上的最小素数  
const int NODE_NUMBER = 1200010;//node个数  
  
int hashTable[HASH_BASE];  
int cur;  
  
struct HashNode{  
    int num[6];  
    int next;  
};  
  
HashNode node[NODE_NUMBER];  
  
void initHashTable()  
{  
    cur = 0;  
    for (int i = 0; i < HASH_BASE; i++)  
    {  
        hashTable[i] = -1;  
    }  
}  


哈希函数:

unsigned getHash(int num[])  
{  
    unsigned int value = 0;  
    for (int i = 0; i < 6; i++)  
    {  
        value += num[i];  
    }  
    return value%HASH_BASE;  
}


插入数据:
void insertHashNode(int num[], unsigned value)  
{  
    for (int i = 0; i < 6; i++)  
    {  
        node[cur].num[i] = num[i];  
    }  
    node[cur].next = hashTable[value];  
    hashTable[value] = cur;  
    cur++;  
}

程序的进行是一边读数据,一边构建hash table,一边判断当前读到的数据是否与已经在hash table中的数据相等进行的.

bool searchHash(int num[])  
{  
    unsigned value = getHash(num);  
    int next = hashTable[value];  
    while (next != -1)  
    {  
        if (compare(num, node[next].num))  
            return true;  
        next = node[next].next;  
    }  
    insertHashNode(num, value);  
    return false;  
}  
即如果发现该数据的哈希值与其它冲突(hashTable[value]!=-1),就比较是否相等,不想等就插入到表中。


poj3247也是同样模式,最大数据有10W个,即10W行,因此不能直接枚举找最大距离,必须用Hash查找相同行,找到相同行再比较最大距离,看是否更新最大距离。


### 什么是可哈希化 在 Python 中,**可哈希化**是指一个对象可以通过 `__hash__()` 方法生成一个固定的整数作为其哈希,并且能够通过 `__eq__()` 或其他比较方法来判断与其他对象的相等关系[^2]。这意味着,在整个对象生命周期内,只要它的状态不变,它所产生的哈希也应保持一致。 #### 可哈希化的条件 为了使一个对象成为可哈希的对象,需满足以下两点: 1. **固定性**: 对象在整个生命周期内的哈希不应发生变化。 2. **一致性**: 如果两个对象被认为是相等的(`obj1 == obj2` 返回 True),则它们的哈希必须相同;反之亦然,如果两者的哈希不同,则它们一定不相等[^2]。 --- ### 如何实现可哈希化 Python 的内置类型中有一些默认支持哈希操作的类型,比如字符串 (`str`)、元组 (`tuple`) 和数字类型等。然而,当自定义类时,默认情况下这些类实例是不可哈希的。要让自定义类中的对象变得可哈希,需要显式地定义 `__hash__()` 和 `__eq__()` 方法。 以下是具体实现方式: #### 定义 `__hash__()` 方法 此方法用于返回对象的哈希。通常会基于对象的状态属性计算得出唯一的哈希。推荐使用标准库函数 `hash()` 来辅助完成这一过程。 #### 定义 `__eq__()` 方法 此方法用来判定当前对象是否等于另一个对象。只有当两个对象被认定为逻辑上的“相等”时,才允许它们共享同一个哈希。 下面是一个简单的例子展示如何创建一个可哈希化的类: ```python class Point: def __init__(self, x, y): self.x = x self.y = y def __eq__(self, other): if isinstance(other, Point): return self.x == other.x and self.y == other.y return False def __hash__(self): return hash((self.x, self.y)) ``` 在这个例子中,我们重写了 `Point` 类的 `__eq__()` 和 `__hash__()` 方法。这样做的目的是为了让每一个拥有特定坐标 `(x,y)` 的点都能唯一对应到某个固定的哈希上。 需要注意的是,一旦实现了这两个特殊的方法之后,该类型的任何实例都可以安全地放入集合(set)或者字典(dictionary)这样的容器结构里去存储和检索了——因为这些数据结构内部依赖于成员元素具备良好的哈希行为特性来进行高效查找与管理。 --- ### 哈希冲突处理简介 尽管理想状态下不同的输入应该映射成完全不一样的输出结果,但在实际应用过程中由于目标空间有限等原因不可避免会出现所谓的「哈希碰撞」情况发生,也就是多个源数据经过同一套算法转换后得到重复的目标编码串的现象[^3]。针对这种情况一般有两种主流解决方案:链表法(Chaining)以及开放寻址法(Open Addressing),不过这部分内容超出了单纯讨论“可哈希”的范畴。 ---
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值