记录下map 和unordered_map的用法

                                    “ 多做善事才是好运的根本!”

2018年9月14日

8月、9月、10月~

挺过去,一切都会好的,

但是竭尽全力,

因为,你后悔不起~

记录下C++、数据结构中的一些知识用法吧:

我们都知道,容器是存放数据的地方,常见的容器有序列式容器和关联式容器,序列式容器,即其中的元素不一定有序,但可以被排序,比如vector、list、queue、stack、heap、priority_queue;而关联式容器内部结构基本上是一个平衡二叉树。所谓关联,指每个元素都有一个键值和一个实值<key,value>,元素按照一定的规则存放。比如RB-tree、set、map、unordered_map、hashtable、hash_map、hash_set。

接下来着重介绍map和unordered_map:(用的最多)

map: #include <map>
unordered_map: #include <unordered_map>

算了,说一下map和set的区别吧,set:其内部元素会根据元素的键值自动被排序;区别于map,它的键值就是实值,而map可以同时拥有不同的键值和实值。

map:

          一对一的方式来存储数据,<关键字,映射值>,其内部通过R-B tree(红黑树)实现,而且会根据key值来自动将数据排序,因此map内部的所有元素都是有序的,红黑树的每一个节点都代表着map的一个元素。因此,对于map进行的查找,删除,添加等一系列的操作都相当于是对红黑树进行的操作。另外,map比hash_map(未进入stl)稳定,但是一般没有hash_map快。其时间复杂度:O(log n)

unordered_map:

       unordered_map底层用一个哈希表(也叫散列表,通过把关键码值映射到Hash表中一个位置来访问记录,查找的时间复杂度可达到O(1),其在海量数据处理中有着广泛应用)来实现。因此,其元素的排列顺序是无序的。时间复杂度:O(1)常数级

明确下各自的优缺点:

map:

  1. 优点: 
    1. 有序性,这是map结构最大的优点,其元素的有序性在很多应用中都会简化很多的操作
    2. 红黑树,内部实现一个红黑书使得map的很多操作在lgn的时间复杂度下就可以实现,因此效率非常的高
  2. 缺点: 空间占用率高,因为map内部实现了红黑树,虽然提高了运行效率,但是因为每一个节点都需要额外保存父节点、孩子节点和红/黑性质,使得每一个节点都占用大量的空间

  3. 适用处:对于那些有顺序要求的问题,用map会更高效一些

unordered_map:

  1. 优点: 因为内部实现了哈希表,因此其查找速度非常的快
  2. 缺点: 哈希表的建立比较耗费时间
  3. 适用处:对于查找问题,unordered_map会更加高效一些,因此遇到查找问题,常会考虑一下用unordered_map

举例:(包括map的声明、建立、遍历)

leetcode 1两数之和

/*
题目:leetcode 1 Two Sum 两数之和
      从给定的一组数中找到两个数的和为target.返回两个数的序号,假设每次输入只有一组解
时间:2018年9月14日 12:16:34
思路:1.暴力搜索,对于每个数去找后面和它的和为target的数,如果找到了就返回,时间复杂度O(n^2)
      2.hash:先进行hash映射,<key,value>为 <nums[i], i>,对于每一个数,可以在O(1)的时间找到
  即:用空间来弥补时间,建立使用一个HashMap,来建立数字和其下标位置之间的映射,也就是我求得一个数就直接能知道它的下标。
      我们都知道HashMap是常数级的查找效率,这样,我们在遍历数组的时候,用target减去遍历到的数字,就是另一个需要的数字了,
      直接在HashMap中查找其是否存在即可,注意要判断查找到的数字不是第一个数字,比如target是4,遍历到了一个2,那么另外一个2不能是之前那个2,
      整个实现步骤为:先遍历一遍数组,建立HashMap映射,然后再遍历一遍,开始查找,找到则记录index。
*/


#include <bits/stdc++.h>

using namespace std;

//法一:暴力搜索
class Solution {
public:
    vector<int> twoSum(vector<int> &num, int target) {
        vector<int> v;
        for(int i=0;i<num.size();++i)
        {
            for(int j=i+1;j<num.size();++j)
            {
                if(num[i]+num[j]==target)
                {
                    v.push_back(i);
                    v.push_back(j);
                    break;
                }
            }
        }
        return v;
    }
};

//法二:hash表
class Solution {
public:
    vector<int> twoSum(vector<int> &num, int target) {
        vector<int> v;
        unordered_map<int,int> m;//声明hash图
        for(int i=0;i<num.size();++i)//建立hash图
        {
            m[num[i]]=i;
        }
        
        for(auto &it:m)//遍历hash图;
            cout<<it.first<<" "<<it.second<<endl;
        for(int i=0;i<num.size();++i)
        {
            int t=target-num[i];
            if(m.count(t)&& m[t]!=i)//if(m.find(t)!=m.end()&&m[t]!=i)
            {
                v.push_back(i);
                v.push_back(m[t]);
                break;
            }
        }
        return v;
    }
};

int main()
{
    vector<int> a={1,6,4,5,7};
    Solution so;
    vector<int> res;
    res=so.twoSum(a,9);
    for(auto i:res)//遍历容器的简单方法
        cout<<i<<" ";
    return 0;
}

一定要看懂,理解!

里面的写法很值得铭记。

最后,祝福所有努力的人,都会有好运!

猜你喜欢

转载自blog.csdn.net/m0_38087936/article/details/82705501