动态分配到二维std::unordered_map

Dynamically allocating into a 2 dimensional std::unordered_map

本文关键字:std unordered map 二维 动态分配      更新时间:2023-10-16

我有一个2d map声明为

    unordered_map< string, unordered_map<string, Road*>* > matrix;

取Road

的一个实例
class Road {
public:
    Road() : connected(0), weight(0) {}
    bool connected;
    int weight;
};

我分配如下

void addPlace(string place) {
    // error checking
    if (placeExists(place)) {
        cout << "Place already exists" << endl;
        return;
    }
    Road *road = new Road();
    unordered_map<string, Road*> *newRelationship = new unordered_map<string, Road*>;
    newRelationship->insert({ {place},{road} });
    // add to network
    matrix.insert({ { place },{ newRelationship } });
    ++n_verticies;
}
然而,当我调用 时
void connectPlace(string source, string dest, int w)
    if (!placeExists(dest) || !placeExists(source)) {
        cout << "Place(s) does not exists" << endl;
        return;
    }
     ...
     if (matrix.find(source)->second->find(dest)->second->connected)

我得到一个错误:"列表迭代器是不可解引用的",这表明我已经走错了我的分配?提前谢谢你。

下面是我对placeExists的调用,它在connectPlace的两次调用中都返回true:

bool placeExists(string place) {
    if (matrix.find(place) == matrix.end()) {
        return false;
    }
    return true;
}

我已经把它分解成

    auto a = matrix.find(source);
    auto b = matrix.find(source)->second;
    auto c = matrix.find(source)->second->find(dest); // (<Error reading characters of string.>, {connected=??? weight=??? })
    auto d = matrix.find(source)->second->find(dest)->second; // stops here
    auto e = matrix.find(source)->second->find(dest)->second->connected;

我的函数调用如下

Graph *road_network = new Graph(false);
road_network->addPlace("Sacremento");
road_network->addPlace("Antelope");
road_network->addPlace("Roseville");
road_network->addPlace("San Francisco");
road_network->addPlace("San Jose");
road_network->addPlace("Davis");
road_network->addPlace("Los Angelous");
road_network->connectPlace("Sacremento", "Antelope", 5); //<-- break
road_network->connectPlace("San Francisco", "San Jose", 2);
road_network->connectPlace("Los Angelous", "Davis", 10);
road_network->connectPlace("Davis", "Antelope", 4);
road_network->connectPlace("Roseville", "Davis", 5);
road_network->connectPlace("San Jose", "Antelope", 6);
road_network->connectPlace("Davis", "Los Angelous", 5);

一个很大的问题是你试图在一行代码中做太多的事情。

if (matrix.find(source)->second->find(dest)->second->connected)

应该分成几行。具体来说,在继续之前,您需要确保对find()的任何调用实际上都成功:

auto found = matrix.find(source);
if (found != matrix.end()) {
    // keep going
}
else {
    // print error message
}

就我个人而言,我更喜欢这个解决方案,而不是重构您的placeExists(),原因有两个:

  1. 避免多次调用find()
  2. 这显式地显示了每个数据结构的每次访问。
  3. 它避免了当一个键存在于matrix时,它也存在于嵌套的unordered_map中的假设。

事情出错的地方是在你的addPlace()函数内。代码:

Road *road = new Road();
unordered_map<string, Road*> *newRelationship = new unordered_map<string, Road*>;
newRelationship->insert({ {place},{road} });
// add to network
matrix.insert({ { place },{ newRelationship } });

创建了一条新的道路,它可以代表从城市到自身的连接,但不代表与任何其他城市的连接。例如,在调用

之后
road_network->addPlace("Sacremento");

你的matrix看起来像:

  • "Sacremento"
    • "Sacremento":& lt; Road>

在你打电话给

之后
road_network->addPlace("Antelope");

它看起来像:

  • "Sacremento"
    • "Sacremento":& lt; Road>
  • "羚羊"
    • "羚羊":& lt; Road>

因此,稍后当您尝试执行road_network->connectPlace("Sacremento", "Antelope", 5);时,它会在matrix映射中的键"Sacremento"下查找unordered_map中键为"Antelope"的条目,该条目不存在。因此,当您试图解引用matrix.find(source)->second->find(dest)创建的迭代器并访问其second成员时,它会抛出错误,因为该迭代器无效。

有两种方法可以解决这个问题:
  1. addPlace被调用时,为matrix中每个已存在的位置在newRelationship中添加一个条目,为matrix中每个已存在的位置在unordered_map中添加一个条目。(对于大型数据集,无论是存储还是处理,这都是非常低效的。存储效率低下,因为它必须存储(位置数)^2个条目,其中许多条目可能未被使用。处理效率低下,因为每次添加一个新位置时,每个现有的位置都必须循环通过)
  2. addPlace中,只需在place下的matrix中添加一个空的unordered_map。在connectPlace中,如果matrix.find(source)->second->find(dest)返回一个无效的迭代器(由返回值是否等于matrix.end()确定),则在matrix中的source键下添加一个新条目unordered_map,键为dest,值为具有给定权重的新Road对象。