You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

unordered_multimap元素乱序原因及按插入序输出的修改方法

std::unordered_multimap输出顺序与插入顺序不符的原因及解决方法

问题描述

编写了如下C++代码,预期按元素插入顺序输出,但实际输出顺序与插入顺序不符:

#include <iostream>
#include <map>
#include <unordered_map>

int main ()
{
  std::unordered_multimap<std::string, std::string> mymm;

  mymm.insert(std::make_pair("key6","50"));
  mymm.insert(std::make_pair("key1","150"));
  mymm.insert(std::make_pair("key4","300"));
  mymm.insert(std::make_pair("key2","200"));
  mymm.insert(std::make_pair("key5","100"));
  mymm.insert(std::make_pair("key3","250"));

  for (auto x : mymm)
  {
      std::cout << "key:"<<x.first<<":value:"<<x.second<<std::endl;;
  }

  return 0;
}

实际输出:

key:key5:value:100
key:key4:value:300
key:key1:value:150
key:key3:value:250
key:key6:value:50
key:key2:value:200

原因分析

std::unordered_multimap的底层实现是哈希表,元素的存储位置由键的哈希值计算得出,遍历顺序取决于哈希表的内部结构和哈希函数的结果,和元素的插入顺序没有关联。这是该容器的设计特性——牺牲顺序性来换取O(1)平均时间复杂度的查找、插入和删除操作。

解决方法

要实现按插入顺序输出元素,有以下几种可行方案:

方案1:同时维护哈希表与顺序容器

如果需要保留std::unordered_multimap的快速查找特性,同时记录插入顺序,可以额外使用std::vector或std::list存储插入的键值对,遍历顺序容器即可按插入顺序输出:

#include <iostream>
#include <unordered_map>
#include <vector>

int main ()
{
  std::unordered_multimap<std::string, std::string> mymm;
  std::vector<std::pair<std::string, std::string>> insertOrder;

  // 插入时同时记录顺序
  auto insertAndRecord = [&](const std::pair<std::string, std::string>& p) {
      mymm.insert(p);
      insertOrder.push_back(p);
  };

  insertAndRecord(std::make_pair("key6","50"));
  insertAndRecord(std::make_pair("key1","150"));
  insertAndRecord(std::make_pair("key4","300"));
  insertAndRecord(std::make_pair("key2","200"));
  insertAndRecord(std::make_pair("key5","100"));
  insertAndRecord(std::make_pair("key3","250"));

  // 遍历顺序容器输出
  for (auto x : insertOrder)
  {
      std::cout << "key:"<<x.first<<":value:"<<x.second<<std::endl;
  }

  return 0;
}

方案2:使用支持插入顺序的第三方容器

如果项目中可以使用Boost库,boost::multi_index_container可以同时支持哈希查找和按插入顺序遍历,它允许为容器定义多个索引类型:

#include <iostream>
#include <string>
#include <boost/multi_index_container.hpp>
#include <boost/multi_index/hashed_index.hpp>
#include <boost/multi_index/identity.hpp>
#include <boost/multi_index/sequenced_index.hpp>

namespace bmi = boost::multi_index;

// 定义支持顺序和哈希索引的容器
using OrderedMultimap = bmi::multi_index_container<
    std::pair<std::string, std::string>,
    bmi::indexed_by<
        // 按插入顺序的索引
        bmi::sequenced<>,
        // 按键哈希的索引
        bmi::hashed_non_unique<bmi::member<std::pair<std::string, std::string>, std::string, &std::pair<std::string, std::string>::first>>
    >
>;

int main ()
{
  OrderedMultimap mymm;

  mymm.insert(std::make_pair("key6","50"));
  mymm.insert(std::make_pair("key1","150"));
  mymm.insert(std::make_pair("key4","300"));
  mymm.insert(std::make_pair("key2","200"));
  mymm.insert(std::make_pair("key5","100"));
  mymm.insert(std::make_pair("key3","250"));

  // 默认遍历就是插入顺序
  for (auto x : mymm)
  {
      std::cout << "key:"<<x.first<<":value:"<<x.second<<std::endl;
  }

  return 0;
}

方案3:仅使用顺序容器(无需快速查找时)

如果不需要哈希表的快速查找功能,直接使用std::vector<std::pair<std::string, std::string>>存储元素,遍历自然就是插入顺序,实现最简单。


内容的提问来源于stack exchange,提问作者sreedevi k

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.29 15:02:49