现在的位置: 首页 > 综合 > 正文

数据库技术:map和set的使用及top K问题

2019年11月12日 综合 ⁄ 共 1640字 ⁄ 字号 评论关闭

  1.map和set的应用和比较

  map和set都是关联式容器,底层容器都是红黑树。

  map以键值对的形式进行存储,方便进行查找,关键词起到索引的作用,值则表示与索引相关联的数据,以红黑树的结构实现,插入删除等操作都可以在O(log n)时间内完成。

  所有元素都是键+值存在,key=value组成pair,是一组映射关系。

  不允许键重复

  所有元素是通过键进行自动排序的

  map的键是不能修改的,但是其键对应的值是可以修改的

  

复制代码

  1 #include

  2 #include

  3

  4 //模拟pair和 make_pair的底层实现

  5 //template

  6 //struct pair

  7 //{

  8 // K first;

  9 // V second;

  10 //

  11 // pair(const K& key, const V& value)

  12 // :first(key)

  13 // , second(value)

  14 // {}

  15 //};

  16 //template

  17 //pair make_pair(const K& key, const V& value)

  18 //{

  19 // return pair(key, value);

  20 //}

  21

  22 //vector GetTopKF(const vector& fruits)

  23 //{

  24 // vector topk;

  25 // typedef map CountTop;

  26 // typedef map::iterator CountIt;

  27 // CountTop counttop;

  28 // for (size_t i = 0; i < fruits.size(); i++) {   29 // CountIt countit = counttop.find(fruits[i]);   30 // if (countit != counttop.end())   31 // (countit->second)++;

  32 // else

  33 // //counttop.insert(pair(fruits[i], 1));

  34 // counttop.insert(make_pair(fruits[i], 1));

  35 // }

  36 // return topk;

  37 //}

  38 vector GetTopKF(const vector& fruits)

  39 {

  40 vector topk;

  41 typedef map CountTop;

  42 typedef map::iterator CountIt;

  43 CountTop counttop;

  44 for (size_t i = 0; i < fruits.size(); i++) {   45 /*pair retKV = counttop.insert(make_pair(fruits[i], 1));   46 if (retKV.second == false)   47 {   48 retKV.first->second++;

  49 }*/

  50 counttop[fruits[i]]++;

  51 }

  52 return topk;

  53 }

  54

  55

  56 void MapTest()

  57 {

  58 typedef map Dict;

  59 typedef map::iterator DictIt;

  60 Dict dict;

  61 dict.insert(pair("right", "右边"));

  62 dict.insert(pair("left", "左边"));

  63 dict.insert(pair("世界", "你好"));

  64 dict.insert(pair("hello", "word"));

  65 dict.insert(pair("key", "键值"));

  66

  67 DictIt dictit = dict.begin();

  68 while (dictit != dict.end()) {

  69 cout << (*dictit).first << " " << (*dictit).second << endl;   70 ++dictit;   71 }   72 DictIt ret = dict.find("left");   73 if(ret != dict.end())   74 dict.erase(ret);   75 vector v;   76 v.push_back("梨");   77 v.push_back("苹果");   78 v.push_back("西瓜");   79 v.push_back("香蕉");   80 v.push_back("西瓜");   81 v.push_back("香蕉");   82 v.push_back("菠萝");   83 v.push_back("西瓜");   84 v.push_back("草莓");   85 GetTopKF(v);   86 }    复制代码   set支持高效的关键字查询操作---检查每一个给定的关键字是否在set中,也支持高效插入删除。   以平衡二叉检索树实现,查找使用中序遍历算法,检索效率高于vector,deque,list等容器,另外使用中序遍历可将键值按照从小到大遍历出来,构造set集合的主要目的是为了快速检索,不可直接去修改键值。   所得元素的只有key没有value,value就是key   不允许出现键值重复   所有的元素都会被自动排序   不能通过迭代器来改变set的值,因为set的值就是键    复制代码   1 #pragma once   2 #include   3 #include   4 #include   5   6 using namespace std;   7   8 void SetTest()   9 {   10 set s1; //没有数据冗余   11 s1.insert(4);   12 s1.insert(5);   13 s1.insert(7);   14 s1.insert(7);   15 s1.insert(14);   16 s1.insert(7);   17 s1.insert(9);   18 s1.insert(3);   19 s1.insert(0);   20 s1.insert(30);   21 s1.insert(14);   22 s1.insert(6);   23 s1.insert(28); //set的插入操作   24   25 set::iterator ite = s1.begin();   26 //ite = 10;   27 while (ite != s1.end()) { //利用迭代器遍历打印数据   28 cout<<*ite<<" ";   29 ite++;   30 }   31 cout << endl;   32 set::reverse_iterator ret1= s1.rbegin();   33 while (ret1 != s1.rend()) { //降序打印   34 cout << *ret1 << " ";   35 ret1++;   36 }   37   38 set::iterator ret = s1.find(10); //   39 if (ret != s1.end()) //set的查找,如果没有找到不会报错   40 cout << "find it" << *ret << endl;   41 else   42 cout << "null" << endl;   43   44 if (s1.count(14))//只判断是否存在14,返回1或0   45 cout << "find it" << endl;   46 else   47 cout << "null" << endl;   48   49 ret = s1.find(30); //find后删除   50 if (ret != s1.end())   51 s1.erase(ret);   52 set::iterator last, first;   53 first = s1.lower_bound(8); //返回8大的第一个数   54 last = s1.upper_bound(20); //返回20大的第一个数   55 s1.erase(first, last);//删除这个范围的数据   56 s1.erase(100); //有就删除,没有也不报错   57   58 set::iterator ite1 = s1.begin();   59 while (ite1 != s1.end()) {   60 cout << *ite1 << " ";   61 ite1++;   62 }   63 }   64 void MultisetTest() {   65 multiset s2; //允许数据冗余,其他操作同set   66 s2.insert(13);   67 s2.insert(4);   68 s2.insert(6);   69 s2.insert(19);   70 s2.insert(20);   71 s2.insert(16);   72 s2.insert(9);   73 s2.insert(12);   74 s2.insert(9);   75 s2.insert(7);   76 s2.insert(5);   77 s2.insert(13);   78 s2.insert(9);   79 multiset::iterator mit = s2.begin();   80 while (mit != s2.end()) {   81 cout << *mit << " ";   82 mit++;   83 }   84 multiset::iterator mIt = s2.find(20);   85 /*++mIt;   86 ++mIt;   87 ++mIt;   88 ++mIt;*/   89 }    复制代码   map的节点是一对数据,set的节点是一个数据。   2.扩展   Multimap允许数据冗余,即存储的数据不唯一。   hashmap是基于散列表(哈希表,hash table)实现的。基本原理是:使用一个下标范围比较大的数组来存储元素。可以设计一个函数(哈希函数,也叫做散列函数),使得每个元素的关键字都与一个函数值(即数组下标,hash值)相对应,于是用这个数组单元来存储这个元素;也可以简单的理解为,按照关键字为每一个元素“分类”,然后将这个元素存储在相应“类”所对应的地方,称为桶。   但不能够保证每个元素的关键字与函数值是一一对应的,有可能出现对于不同的元素,得到相同的函数值,这就是哈希冲突,往往需要专门的哈希冲突处理函数来解决。   hashma插入和查找的速度与 哈希函数和冲突处理函数的 实现有关,是这两个函数耗时的总和。查询时间复杂度是O(1);   看具体的应用,不一定常数级别的hash_map一定比log(n)级别的map要好,hash_map的hash函数以及解决地址冲突等都要耗时间,而且众所周知hash表是以空间换时间的,因而hash_map的内存消耗肯定要大,一般情况下,如果记录非常大,考虑hash_map,查找效率会高很多,如果要考虑内存消耗,则要谨慎使用hash_map。   Multiset允许数据冗余。

抱歉!评论已关闭.