C ++多图容器如何实现?

问题描述

| 例如,使用动态数组实现C ++向量,其中每个元素使用连续的内存空间。 我知道C ++多图是一对多的关系,但是内部结构是什么?     

解决方法

        C ++标准没有定义标准容器的实现方式,它仅给出了某些约束,例如您对向量所说的约束。 多图具有一定的运行时复杂度(对于感兴趣的操作为O(lg n))和其他保证,并且可以实现为红黑树。这就是在GNU标准C ++库中实现它们的方式。     ,        通常是一棵红黑树。参见例如Dobb博士的STL的红黑树。     ,        除了“首选”答案外,因为这样我不会发表评论: 给定一个具有值B,C,D的键,如果每个元素都有其自己的节点,则迭代器的行为将易于实现。 Find()被定义为返回系列中的第一个结果,随后的迭代使您遍历其余元素。映射和多重映射之间的实际区别在于,多重映射在整个value_type上使用<排序,其中映射仅在key_type上使用< 更正:C ++ 11标准明确规定,在具有相同键的任何现有值的末尾插入新(键,映射)对。这就提出了一个我从未考虑过的问题:多图可以包含两个节点,其中键和映射目标都相同。该标准对此似乎没有明确的立场,但是值得注意的是,映射类型不需要比较运算符。如果编写测试程序,则会发现一个多重映射可以将X映射到1、2、1。即:\“ 1 \”可以多次出现作为目标,并且两个实例不会合并。对于某些算法而言,这是一个缺陷。 Dobbs博士的这篇文章讨论了常用的底层rb-tree实现。需要注意的主要一点是,重新平衡操作实际上根本不关心密钥,这就是为什么您可以构建一个允许重复密钥的rb-tree的原因。     ,        就像它的更简单版本(即std :: map)一样,多图主要使用红黑树构建。 C ++标准本身未指定实现。但是在大多数情况下(我亲自检查了SGI STL)都使用了红黑树。红黑树是高度平衡的树,因此对它们的读取/读取操作始终保证为O(log(n))时间。但是,如果您想知道密钥的值是如何存储的。每个
key->pair
被保存为红黑树中的单独节点(即使相同的键可能多次出现,就像下面的键
\'b\'
一样)。键用于查找/搜索rb树。找到密钥后,将返回存储在节点中的密钥值。
  std::multimap<char,int> mmp;

  mmp.insert(std::pair<char,int>(\'a\',10));
  mmp.insert(std::pair<char,int>(\'b\',20));
  mmp.insert(std::pair<char,15));
  mmp.insert(std::pair<char,int>(\'c\',25));
  mmp.insert(std::pair<char,7));


for (std::multimap<char,int>::iterator it=mmp.begin(); it!=mmp.end(); ++it){

    std::cout << (*it).first << \" => \"  << (*it).second << \" . Address of (*it).second = \" << &((*it).second) << \'\\n\';
}
输出:
a => 10 . Address of (*it).second = 0x96cca24
a => 15 . Address of (*it).second = 0x96ccae4
a => 7 . Address of (*it).second = 0x96ccb04
b => 20 . Address of (*it).second = 0x96cca44
b => 10 . Address of (*it).second = 0x96cca64
b => 15 . Address of (*it).second = 0x96cca84
b => 20 . Address of (*it).second = 0x96ccaa4
c => 25 . Address of (*it).second = 0x96ccac4
最初,我认为像\'b \'这样的单个键的值可能存储在std :: vector中。
template <class K,class V>
struct Node {
  K key;
  std::vector<V> values; 
  struct Node* left;
  struct Node* right;
}
但是后来我意识到这会违反O(log(n))的保证获取时间。此外,打印出值的地址可确认具有公共密钥的值不连续。 它们的键是使用operator <插入的,因此具有相同键的值将按插入顺序存储。 所以如果我们先插入 (键= \'b \',值= 20) 接着 (键= \'b \',值= 10) 插入是使用operator <完成的,因为第二个\'b \'不小于第一个插入的\'b \',所以它被插入到\'二叉树的右分支\'中。 我使用的编译器是gcc-5.1(C ++ 14)。