使两个不同指针之间的对应关系到同一个类

时间:2013-06-09 21:53:38

标签: c++ algorithm

假设我有一张我要复制的城市地图。问题是from类中的toroad是特定cityMap对象的内存中的指针。使一个新对象独立于被复制的对象将意味着每个城市将具有不同的指针值。什么是在我要复制的cityMap和我在cityMap方法中创建的新copy中的道路之间建立对应关系的智能方法?

创意1(慢一点,我觉得它很难看)就是制作map<road *, road *>

创意2(我觉得这很难看,因为它为一个较低的类添加了一个不需要将该类作为概念实现的成员,但在O(N)构造时间之后是O(1)查找时间)是roadroad *correspondingRoad的成员newRoad->to = oldRoad->to->correspondingRoad。然后,我只能说class cityMap { public: vector<roads *> allRoads // all raods in the area vector<city *> cities; // all the cities in the area cityMap *copy(); // makes a copy of the entire map }; class roads { public: city *from, *to; } class city { public: vector<raod *> roads; // roads from this city to another city }

有没有一个很好的方法来设置这一切?我希望O(1)查找时间(不是地图),没有太多的施工时间(不是地图),并且让道路类不被不相关的类想要的东西所取代。也就是说,对应于完全相同的道路的新创建的道路不是道路概念的一部分,它仅是复制城市地图的概念的一部分。

{{1}}

1 个答案:

答案 0 :(得分:1)

如果我理解你的话,我认为您想要执行城市地图的深层复制,并且正在寻找一种方法,您可以有效地确保新对象之间的关系是和旧的关系一样。

我同意这个想法2,在路上有一个额外的成员,代表从旧到新的映射,是可怕的。但是我没有看到想法1有很多错误,使用map来表示从原始道路到新道路的映射,尽管我认为您还需要从旧城市到新城市以及从旧路到新路。如果您有map,它只会是一个临时地图,只有在copy方法中才需要,而您在新城市地图上的操作可能需要的时间比复制时间长。此外,map是一个库类,因此将进行相当好的优化。如果您使用的是C ++ 11(或者可以访问boost),则可以使用unordered_map形状的哈希映射,它可以提供平均O(1)而不是对数查找。这种方法给出了:

using std::vector;
using std::unordered_map;

class road;
class city;

class cityMap
{
public:
    vector<road *> allRoads;    // all raods in the area
    vector<city *> cities;      // all the cities in the area
    cityMap *copy()             // makes a copy of the entire map
    {
        cityMap* pNewCityMap = new cityMap;
        // create new cities, building up old city to new city map
        unordered_map<city*, city*> city2city;
        for(city* pOldCity: cities) {
            city* pNewCity = new city(*pOldCity);
            pNewCityMap->cities.push_back(pNewCity);
            city2city[pOldCity] = pNewCity;
        }
        // create new roads, building up old road to new road map
        unordered_map<road*, road*> road2road;
        for(road* pOldRoad: allRoads) {
            road* pNewRoad = new road(city2city[pOldRoad->from], city2city[pOldRoad->to]);
            pNewCityMap->allRoads.push_back(pNewRoad);
            road2road[pOldRoad] = pNewRoad;
        }
        // fix up roads in new cities
        for(city* pNewCity: pNewCityMap->cities) {
            for(road*& pNewRoad: pNewCity->roads) {
                pNewRoad = road2road[pNewRoad];
            }
        }
        return pNewCityMap;
    }
};

class road
{
public:
    city *from, *to;
    road(city* _from, city* _to) : from(_from), to(_to) {}
};

class city
{
public:
    vector<road *> roads;       // roads from this city to another city
};

替代方法的灵感来自celtschk的评论,并使用索引来表示道路。在这种情况下,城市地图仍然可以返回road类,但必须在内部存储其索引方面的道路。下面是草图实现。

using std::pair;
typedef size_t roadnum;

class city2
{
public:
    vector<roadnum> roads;       // roads from this city to another city
};

class road2
{
public:
    city2 *from, *to;
    road2(city2* _from, city2* _to) : from(_from), to(_to) {}
};

class cityMap2
{
    vector<pair<size_t, size_t>> allRoads;    // all raods in the area, pairs of city indices
public:
    vector<city2 *> cities;      // all the cities in the area
    cityMap2 *copy();             // makes a copy of the entire map

    size_t GetNumberRoads() const { return allRoads.size(); }
    road2 GetRoad(size_t which) const
    {
        const pair<size_t, size_t>& citycity = allRoads[which];
        return road2(cities[citycity.first], cities[citycity.second]);
    }
};