哈希表

Posted ffxpy

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了哈希表相关的知识,希望对你有一定的参考价值。

符号表是一种以集合为基础,支持查询插入删除操作的抽象数据类型。
用数组实现的符号表,通常带一个游标指示最后一个元素在数组的储存位置,优点是结构简单,易于操作,缺点是集合的大小受数组大小限制,三个操作在最坏情况下都需要o(n)复杂度,通常集合元素并不占满整个数组,储存空间没有得到充分利用。
因此需要用哈希表(散列表)实现符号表。哈希表就是一种以键值存储数据的结构,我们只要输入待查找的值即key,即可查找到其对应的值。因此只要o(1)时间便可进行操作。然而处理数据间的冲突成为问题。

开散列

拉链法 当有不同元素被映射到同一个位置,将这个位置拉出一个链表,链接相同键值的元素。

三角形 题意就是给出几组三角形的边长,每个三角形有其权值。问属于同一类相似三角形的最大权值。

这题可以用开散列做。用gcd把每个三角形的最小边长相似三角形求出,三边之和作为它的键值。然后拉出链表,链表中每个节点是不同的三角形(他们的共同点是边长之和相同),把三边长从大到小排列,一一对应比较来区分。用结构体数组指针实现。

#include<iostream>
#include<cstring>
using namespace std;
int max(int a, int b) { return a > b ? a : b; }
int min(int a, int b) { return a < b ? a : b; }
int gcd(int a, int b){
    int t = 0;
    while (b){
        t = a%b;
        a = b;
        b = t;
    }
    return a;
}
const int tablesize = 300000;
struct node {
    int val;
    int flag;
    int a, b, c;
    node *next;
}*table[tablesize];
int main() {
    int key;
    int i, n, m, a0, b0, c0, val, a1, b1, c1;
    cin >> n;
    for (i = 1;i < tablesize;i++) {
        table[i] = new node;
        table[i]->a = table[i]->b = table[i]->c = 0;
        table[i]->val = -0x3f;
        table[i]->next = NULL;
    }
    for (i = 0;i < n;i++) {
        cin >> a1 >> b1 >> c1 >> val;
        a0 = a1 / gcd(a1, gcd(b1, c1));
        b0 = b1 / gcd(a1, gcd(b1, c1));
        c0 = c1 / gcd(a1, gcd(b1, c1));
        key = a0 + b0 + c0;
        a1 = max(a0, max(b0, c0));
        c1 = min(a0, min(b0, c0));
        b1 = key - a1 - c1;//将a0b0c0从大到小排序
        node *p = table[key];//!!!!!!!!!重要,等于设了一个游标
        while (1) {
            if (p->a == 0 && p->b == 0 && p->c == 0) {
                p->a = a1;
                p->b = b1;
                p->c = c1;
                p->val = val;
                p->next = new node;
                p = p->next;
                p->a = p->b = p->c = 0;
                p->val = -0x3f;
                p->next = NULL;
                break;
            }
            else if (p->a == a1 && p->b == b1 && p->c == c1) {
                if (val > p->val) p->val = val;
                break;
            }
            else p = p->next;
        }
    }
    cin >> m;
    for (i = 0;i < n;i++) {
        cin >> a1 >> b1 >> c1;
        a0 = a1 / gcd(a1, gcd(b1, c1));
        b0 = b1 / gcd(a1, gcd(b1, c1));
        c0 = c1 / gcd(a1, gcd(b1, c1));
        key = a0 + b0 + c0;
        a1 = max(a0, max(b0, c0));
        c1 = min(a0, min(b0, c0));
        b1 = key - a1 - c1;
        node *p = table[key];//!!!!!!!!!重要,等于设了一个游标
        int op = 1;
        while (1) {
            if (p->a == 0 && p->b == 0 && p->c == 0) {
                op = 0;
                break;
            }
            else if (p->a == a1 && p->b == b1 && p->c == c1) {
                cout << p->val << endl;
                break;
            }
            else p = p->next;
        }
        if (!op) cout << "Sorry" << endl;
    }
    return 0;

}

很迷的是,这题我一直a不了 以上代码只有一个ac 并且找不出bug

闭散列

一个桶中只存放一个元素,当出现冲突时,需进行探测,找到空桶存放冲突元素。

散列函数的构造方法:
直接定址法:取关键字的某个线性函数值作为散列地址
除留余数法:取关键字的某个不大于表长的数除后所得余数作为散列地址
平方取中法:取关键字平方后中间几位作为散列地址
折叠法:将关键字分成几个部分,将这几个部分进行运算所得的值作为散列地址
数值分析法:发现关键字之间的规律构造函数

处理冲突的方法:

线性探测法:当出现冲突时,用取散列长度的模的方法来找下一个位置。hi(k)=(h(k)+di)mod m
m为散列长度 di取1,2…m-1

未完

成绩查询 输出n个学生的成绩并查询。学生的成绩由字符串构成,长度不超过4。

显然暴力求解不行,可以尝试用哈希表做。将名字字符转化为散列表。将每个字母等效为一个二十六进制数。设姓名为(ABCD)26, 散列函数为H(x)=((A*26+B)*26+C)*26+D。

#include<iostream>
#include<string>
#include<cstdlib>
using namespace std;
int a[500000];
int main() {
    memset(a, -1, sizeof(a));
    int n, m;
    cin >> n >> m;
    string h;
    int i, j, len, sum, score;
    for (i = 0;i < n;i++) {
        cin >> h >> score;
        len = h.length();
        sum = h[0] - a + 1;
        for (j = 1;j < len;j++) {
            sum = sum * 26 + h[j] - a + 1;
        }
        a[sum] = score;
    }
    for (i = 0;i < m;i++) {
        cin >> h;
        len = h.length();
        sum = h[0] - a + 1;
        for (j = 1;j < len;j++) {
            sum = sum * 26 + h[j] - a + 1;
        }
        if (a[sum] >= 0) cout << a[sum] << endl;
        else cout << "not,exist!" << endl;
    }
    return 0;
}

 

以上是关于哈希表的主要内容,如果未能解决你的问题,请参考以下文章

下文中的哈希片段指的是啥?

URL片段的最大长度(哈希)

URL的PHP​​和哈希/片段部分

从 URL 获取片段(哈希“#”后的值)[关闭]

带有哈希片段的锚未导航到匹配的 id

一致性哈希算法PHP测试片段