【问题标题】:How to associate to a number another number without using array如何在不使用数组的情况下将一个数字关联到另一个数字
【发布时间】:2011-01-20 12:59:16
【问题描述】:

假设我们已经阅读了这些值:

3
1241
124515
5322353
341
43262267234
1241
1241
3213131

我有一个这样的数组(包含上面的元素):

a[0]=1241
a[1]=124515
a[2]=43262267234
a[3]=3
...

问题是数组中元素的顺序不是恒定的(我必须在程序的其他地方更改它)。

我如何知道一个元素出现在读取文档中的哪个位置。

请注意,我不能这样做:

vector <int> a[1000000000000];
a[number].push_back(all_positions);

因为 a 太大(存在内存限制)。 (假设我只有 3000 个元素,但它们的值是从 0 到 2^32)

因此,在上面的示例中,我想知道 1241 出现的所有位置,而无需再次遍历所有读取的元素。

换句话说,我如何将位置“1,6,7”与数字“1241”相关联,以便我可以在 O(1) 中简单地访问它们(其中 1 实际上是元素出现的位置数)

如果没有 O(1) 我想知道什么是最优的... 不知道我有没有说清楚。如果没有,请说出来,我会更新我的问题:)

【问题讨论】:

  • a 是我保存元素的数组的名称
  • vector&lt;int&gt; 不会比原始数组大。如果值很高,它的内存占用不会增加。
  • int a[1000000000000] 已经是我可以“负担”的更多了。 vecotr a[1000000000000] 不是已经在使用 4*1000000000000 字节了吗?
  • 我认为你误解了asymptotic analysis:“O(1)(其中 1 实际上是元素出现的位置数)”。
  • 我的意思是,如果只有 1 个位置,它就是 1。如果有 N 个位置,则为 N。

标签: c++ key


【解决方案1】:

您需要使用某种动态数组,例如向量 (std::vector) 或其他类似容器(std::list,也许,这取决于您的需要)。

此类数据结构比 C 风格的数组更安全、更易于使用,因为它们负责内存管理。

如果您还需要在 O(1) 中查找元素,您应该考虑使用一些结构,这些结构将索引与项目相关联,并将项目与索引相关联。我不认为 STL 提供任何东西,但 boost 应该有类似的东西。

如果 O(log n) 是您可以承受的成本,也可以考虑 std::map

【讨论】:

  • 如果你可以使用boost::hash_map,你可以获得O(1)。
【解决方案2】:

您可以使用通常所说的multimap。也就是说,它存储了 Key 和多个值。这是一个 O(log) 查找时间。

如果您使用的是 Visual Studio,他们会提供自己的 hash_multimap,否则我是否可以建议使用 Boost::unordered_map 并将列表作为您的值?

【讨论】:

    【解决方案3】:

    您不需要包含 1000000000000 个元素的稀疏数组;使用 std::map 将位置映射到值。

    如果您想要双向查找(即,您有时想要“这个值的索引是什么?”,有时是“这个索引处的值是什么?”),那么您可以使用boost::bimap

    由于值多次出现,事情变得更加复杂。您可以牺牲双向查找并使用std::multimap

    【讨论】:

      【解决方案4】:

      您可以为此使用地图。喜欢:

      std::map<int, std::vector<int>> MyMap;
      

      所以每次你在读取文件时遇到一个值,你都会将它的位置附加到地图上。假设 X 是您读取的值,Y 是位置,那么您就这样做

      MyMap[X].push_back( Y );
      

      【讨论】:

      • 访问 MyMap[x][y] 的复杂度是多少?是 O(1) 吗?
      • 应该是 O(log n)。如果这方面的性能是一个问题,您应该像其他人建议的那样使用哈希图。
      【解决方案5】:

      而不是你的数组使用

      std::map<int, vector<int> > a;
      

      【讨论】:

        【解决方案6】:

        您需要一个关联集合,但您可能希望与多个值关联。

        您可以使用std::multimap&lt; int, int &gt;

        你可以使用std::map&lt; int, std::set&lt; int &gt; &gt;

        我在实践中发现,如果您只需要删除一个元素,后者更容易删除项目。它在键值组合上是唯一的,但不是仅在键或值上。

        如果您需要更高的性能,那么您可能希望使用 hash_map 而不是 map。对于内部集合,尽管使用散列不会获得太多性能,因为重复项很少,最好使用 std::set。

        hash_map 的实现有很多,而且在新标准中。如果您没有新标准,请寻求提升。

        【讨论】:

          【解决方案7】:

          看来您需要std::map&lt;int,int&gt;。可以存储1241-&gt;0124515-&gt;1等映射,然后在这个映射上查找得到数组索引。

          【讨论】:

            【解决方案8】:

            除了这里其他人提供的std::map 解决方案(O(log n))之外,还有哈希映射的方法(在C++0x 中实现为boost::unordered_mapstd::unordered_map,现代编译器支持)。

            它会给你 O(1) 的查找平均often 比基于树的std::map 更快。自己试试吧。

            【讨论】:

              【解决方案9】:

              您可以使用std::multimap 来存储一个键(例如 1241)和多个值(例如 1、6 和 7)。

              insert 具有对数复杂度,但如果您向 insert 方法提供可以插入项目的提示,则可以加快速度。

              【讨论】:

                【解决方案10】:

                对于 O(1) 查找,您可以对数字进行哈希处理以在哈希映射(boost::unordered_map、字典、stdex::hash_map 等)中找到其条目(键)

                该值可以是出现数字的索引向量或 3000 位数组(375 字节),其中设置了出现数字(键)的每个索引的位数。

                boost::unordered_map<unsigned long, std::vector<unsigned long>> myMap;
                for(unsigned long i = 0; i < sizeof(a)/sizeof(*a); ++i)
                {
                   myMap[a[i]].push_back(i);
                }
                

                【讨论】:

                  【解决方案11】:

                  您可以将包含整数值及其所有位置的结构数组存储在数组或向量中,而不是存储整数数组。

                  【讨论】:

                  • 好的,但是如果我有数字 21312312,我必须遍历数组中的所有结构,直到找到值为“21312312”的结构。这不是那么“最佳”:D
                  猜你喜欢
                  • 1970-01-01
                  • 2015-10-18
                  • 2013-08-23
                  • 1970-01-01
                  • 2018-08-10
                  • 2019-09-04
                  • 1970-01-01
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多