映射的应用:哈希表,多维哈希表,多级映射实现字典

看了标题之后你会发现原来映射的功能竟然如此强劲

我们通常所用的map其实就是一棵红黑树,如果有平衡树问题能够用它来解决一定要用,不要手写了,因为红黑树的效率是非常棒的

先看几个定义:

map<string,int> m1;
map<string,map<string,int> >m2;
multiset<string> s1;
multimap<string,string> m3;

其中m1就是一个关联数组,为了模拟普通哈希表

(这里的所有的都是用红黑树实现的,如果你想用哈希表实现,请直接把map替换成hash_map,在空间足够的情况下)

m2是二维哈希表

s1在之前介绍集合的时候没有提到,这里再提一下,这是允许有重复元素的STL集合,学名多级集合

m3就是一个多级映射,允许一个x对应多个y的情况,这样便于实现字典

我们一个一个介绍,s1就不介绍了,和set的用法完全一致

首先是实现最简单的哈希表功能:

    string word;
    int n;
    cin>>n;
    for(int i=1;i<=n;i++)
    {
        cin>>word;
        ++m1[word];
    }
    int m;
    cin>>m;
    for(int i=1;i<=m;i++)
    {
        cin>>word;
        if(m1.count(word))
            cout<<"Yes"<<endl;
        else
            cout<<"No"<<endl;
    }

我们可以看到完全不用手写哈希了,而且如果你想改哈希函数,那么替换成hash_map之后直接重载就好了,这里就不多介绍了

如果我们想删除一个键值对,也非常简单,按键删除就行了

    int l;
    cin>>l;
    for(int i=1;i<=l;i++)
    {
        cin>>word;
        m1.erase(word);
    }

如果你想枚举当前所有的映射情况的话:

    for(map<string,int>::iterator it=m1.begin();it!=m1.end();++it)
        cout<<"key: "<<it->first <<" value: "<<it->second<<endl;

知道iterator写后面就没问题了

然后介绍二维哈希表:

    cin>>n;
    for(int i=1;i<=n;i++)
    {
        string t1,t2;
        int num;
        cin>>t1>>t2>>num;
        m2[t1][t2]+=num;
    }

        for(map<string,map<string,int> >::iterator it=m2.begin();it!=m2.end();it++)
        {
            cout<<it->first<<",";
            for(map<string,int>::iterator it_2=it->second.begin();it_2!=it->second.end();it_2++)
            {
                cout<<it_2->first<<":"<<it_2->second<<endl;
            }
        }

记住这个for循环的操作还是很有必要的,用的时候记得替换成hash_map,不然就是树套树了

如果你想实现字典的话,要注意的是多级映射不能直接用下标那么赋值,需要Insert的是pair类型的变量

    typedef pair<string,string> dic;
    dic d1("smart","klug");
    dic d2("clever","raffiniert");
    dic d3("smart","seltsam");
    m3.insert(d1);
    m3.insert(d2);
    m3.insert(d3);
    word="smart";
    for(multimap<string,string>::iterator pos=m3.lower_bound(word);pos!=m3.upper_bound(word);++pos)
    {
        cout<<pos->second<<endl;
    }

这样就可以,下面贴出来完整的代码:

 1 #include<iostream>
 2 #include<map>
 3 #include<string>
 4 #include<iterator>
 5 #include<set>
 6 using namespace std;
 7 map<string,int> m1;
 8 map<string,map<string,int> >m2;
 9 multiset<string> s1;
10 multimap<string,string> m3;
11 int main()
12 {
13     string word;
14     int n;
15     cin>>n;
16     for(int i=1;i<=n;i++)
17     {
18         cin>>word;
19         ++m1[word];
20     }
21     int m;
22     cin>>m;
23     for(int i=1;i<=m;i++)
24     {
25         cin>>word;
26         if(m1.count(word))
27             cout<<"Yes"<<endl;
28         else
29             cout<<"No"<<endl;
30     }
31     int l;
32     cin>>l;
33     for(int i=1;i<=l;i++)
34     {
35         cin>>word;
36         m1.erase(word);
37     }
38
39     for(map<string,int>::iterator it=m1.begin();it!=m1.end();++it)
40         cout<<"key: "<<it->first <<" value: "<<it->second<<endl;
41     cin>>n;
42     for(int i=1;i<=n;i++)
43     {
44         string t1,t2;
45         int num;
46         cin>>t1>>t2>>num;
47         m2[t1][t2]+=num;
48     }
49
50         for(map<string,map<string,int> >::iterator it=m2.begin();it!=m2.end();it++)
51         {
52             cout<<it->first<<",";
53             for(map<string,int>::iterator it_2=it->second.begin();it_2!=it->second.end();it_2++)
54             {
55                 cout<<it_2->first<<":"<<it_2->second<<endl;
56             }
57         }
58     typedef pair<string,string> dic;
59     dic d1("smart","klug");
60     dic d2("clever","raffiniert");
61     dic d3("smart","seltsam");
62     m3.insert(d1);
63     m3.insert(d2);
64     m3.insert(d3);
65     word="smart";
66     for(multimap<string,string>::iterator pos=m3.lower_bound(word);pos!=m3.upper_bound(word);++pos)
67     {
68         cout<<pos->second<<endl;
69     }
70     return 0;
71 }

当你会用这些东西之后,很多以前做不到的东西,就都十分简单了

原文地址:https://www.cnblogs.com/aininot260/p/9332794.html

时间: 2024-10-11 19:05:04

映射的应用:哈希表,多维哈希表,多级映射实现字典的相关文章

哈希表和完美哈希

我们知道,通过对数组进行直接寻址(Direct Addressing),可以在 O(1) 时间内访问数组中的任意元素.所以,如果存储空间允许,可以提供一个数组,为每个可能的关键字保留一个位置,就可以应用直接寻址技术. 哈希表(Hash Table)是普通数组概念的推广.当实际存储的的关键字数比可能的关键字总数较小时,这时采用哈希表就会比使用直接数组寻址更为有效.因为哈希表通常采用的数组尺寸与所要存储的关键字数是成比例的. 哈希表是一种动态集合数据结构,在一些合理的假设下,在哈希表中查找一个元素的

哈希表之二哈希函数的构造

了解了hash的思想之后,会发现哈希函数只是将关键字对下标的映射,没有什么特别的标准,冲突的多少就是衡量其好坏. 若对于关键字集合中的任一一个关键字,经哈希函数映像到地址集合中任何一个地址的概率是相等的, 则称此类哈希函数为均匀的(Uniform)哈希函数. 如果关键字能够进过哈希函数计算得出的地址能够均匀地分布在地址区间中,就可以减少冲突. 直接定地址法 H(key)=key或H(key)=a*key+b 直接定址所得地址集合和关键字集合的大小相同,对于不同关键字不会发生冲突,但是实际使用较少

数据结构和算法-数据结构-线性结构-顺序表 链表和哈希表

####################################################### """ # 线性表是最基本的数据结构之一,在实际程序中应用非常广泛,它还经常被用作更复杂的数据结构的实现基础. # 根据线性表的实际存储方式,分为两种实现模型: # 顺序表, # 链表, # 下面分别进行研究, """ ####################################################### &qu

证明与计算(5): 从加密哈希函数到一致性哈希

目录: ** 0x01 [哈希函数] vs [加密哈希函数] ** 0x02 [哈希碰撞] vs [生日问题] ** 0x03 [哈希表] vs [分布式哈希表] ** 0x04 [欧式距离] vs [三角不等式] ** 0x05 [异或距离] vs [前缀路由表] 0x01 [哈希函数] vs [加密哈希函数] 在哈希表计算索引的时候,我们需要一个哈希函数,通过hash(key)来计算key在哈希表里的index.这个地方的哈希函数只要尽量满足均匀分布,周期尽量大,计算速度又足够快等即可.而在

MySQL多表查询之外键、表连接、子查询、索引

一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的.所以说,如果谈到了外键,一定是至少涉及到两张表.例如下面这两张表: 上面有两张表:部门表(dept).员工表(emp).Id=Dept_id,而Dept_id就是员工表中的外键:因为员工表中的员工需要知道自己属于哪个部门,就可以通过外键Dep

MySQL数据库学习笔记(六)----MySQL多表查询之外键、表连接、子查询、索引

注:本文转自:http://www.cnblogs.com/smyhvae/p/4042303.html 本章主要内容: 一.外键 二.表连接 三.子查询 四.索引 一.外键: 1.什么是外键 2.外键语法 3.外键的条件 4.添加外键 5.删除外键 1.什么是外键: 主键:是唯一标识一条记录,不能有重复的,不允许为空,用来保证数据完整性 外键:是另一表的主键, 外键可以有重复的, 可以是空值,用来和其他表建立联系用的.所以说,如果谈到了外键,一定是至少涉及到两张表.例如下面这两张表: 上面有两

mysql表分区(摘自 MySQL表的四种分区类型)

一.什么是表分区通俗地讲表分区是将一大表,根据条件分割成若干个小表.mysql5.1开始支持数据表分区了. 如:某用户表的记录超过了600万条,那么就可以根据入库日期将表分区,也可以根据所在地将表分区.当然也可根据其他的条件分区. 二.为什么要对表进行分区为了改善大型表以及具有各种访问模式的表的可伸缩性,可管理性和提高数据库效率. 分区的一些优点包括: 与单个磁盘或文件系统分区相比,可以存储更多的数据.对于那些已经失去保存意义的数据,通常可以通过删除与那些数据有关的分区,很容易地删除那些数据.相

交易事实表、周期快照事实表和累积快照事实表

在数据仓库领域有一个概念叫Transaction fact table,中文一般翻译为"事务事实表".事务事实表是维度建模的数据仓库中三种基本类型事实表中的一种,另外两种分别是周期快照事实表和累积快照事实表. 事务事实表与周期快照事实表.累积快照事实表使用相同的一致性维度,但是它们在描述业务事实方面是有着非常大的差异的. 事务事实表记录的事务层面的事实,保存的是最原子的数据,也称"原子事实表".事务事实表中的数据在事务事件发生后产生,数据的粒度通常是每个事务一条记录

【分库、分表】MySQL分库分表方案

一.Mysql分库分表方案 1.为什么要分表: 当一张表的数据达到几千万时,你查询一次所花的时间会变多,如果有联合查询的话,我想有可能会死在那儿了.分表的目的就在于此,减小数据库的负担,缩短查询时间. mysql中有一种机制是表锁定和行锁定,是为了保证数据的完整性.表锁定表示你们都不能对这张表进行操作,必须等我对表操作完才行.行锁定也一样,别的sql必须等我对这条数据操作完了,才能对这条数据进行操作. 2. mysql proxy:amoeba 做mysql集群,利用amoeba. 从上层的ja