1

我有以下用于存储经络和纬线的数据结构。

每个制图点存储:
A] 地理和空间坐标、制图变形等。
B] 指向北/南/东/西节点的指针。

它允许存储点之间的关系,首先是它们与经线/平行线的关系...

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
 }; 

经线的数据结构存储经线的经度、经线的起点和终点以及点数。

 class Meridian 
 { 
     private: 
             unsigned int points_count; 
             double longitude; 
             Node2DCart *start; 
             Node2DCart *end; 
 .... 
 }; 

所有点都存储在节点列表中:

typedef std::vector<Node2DCart*> TNodes2DCartList; 

class Node2DCartList 
{ 
     protected: 

             TNodes2DCartList nodes; 

     ... 
}; 

但是为 Node2DList 编写复制构造函数存在一个大问题。Meridian/Parallel 和 Node2Dlist 之间存在循环依赖关系。

复制构造函数使用std::map并用新的点和链接替换旧点和链接,这不是实现问题...但是从类 Meridian 开始/结束的指针指向旧 Node2DList 的点... Node2DList 复制构造函数应该通知所有指向旧的经络Node2DList 点并将所有指针更改为新的 Node2DList 点。这个模型不允许。

可能的解决方案是添加两个指向子午线和平行点所属的指针:

 class Node2DCart 
 { 
     protected: 
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             Node2DCart *left; 
             Node2DCart *right; 
             Node2DCart *top; 
             Node2DCart *bottom; 
 ..... 
             Meridian *m;
             Parallel *p;
 };

恐怕这个提议的模型不好。两个班级之间仍然有自行车参考......有人可以帮我改进它吗?谢谢...

4

2 回答 2

2

有人会帮我改进吗?

在这种情况下,我通常会求助于这样的事情:

 typedef int node_id_t;
 enum { NODE_NULL = 0 };
 // or enum node_id_t { NODE_NULL=0 }; for strict typing.

 class Node2DCart 
 { 
     protected:
             node_id_t id;    // id of the node
             //Coordinates of the point 
             double lat; 
             double lon; 
             double lattrans; 
             double lontrans; 
             double x; 
             double y; 
 ..... 
             //Pointers to adjacent points in geographic network 
             node_id_t left;
             node_id_t right; 
             node_id_t top; 
             node_id_t bottom; 
 ..... 
 };

 class Meridian
 {
     private:
             unsigned int points_count;
             double longitude;
             node_id_t start;
             node_id_t end;
 .... 
 };

 /* ... */

 std::vector<Node2DCart *> node_registry;

 // during initialization:
 node_registry.push_back( NULL );
 // to reserve 0th element to denote the NULL pointer

 Node2DCart *
 GetNode(node_id_t id)
 {
    // placeholder of the id range check
    return node_registry[id];
 };

 node_id_t
 AddNode(Node2DCart *n)
 {
    node_registry.push_back(n);
    return node_id_t(node_registry.size()-1);
 };

然后使用数字node_id_t代替Node2DCart *. 还可以添加一个std::set(或std::map在 中更新/测试AddNode())以确保所有 Node2DCart 对象都是唯一的,并且如果不重用现有对象的 id。

本质上是一种寻址方案,为每个节点提供一个唯一的全局标识符。不是最好/最简单的解决方案,使用全局容器,但不止一次帮助了我。特别是为了避免内存泄漏并确保彻底销毁相互依赖的对象的整个层次结构。

代替typedef int node_id_t一个也可以使用struct node_id_t { int id; };和重载转换运算符来简化节点 ID 查找。

于 2010-09-09T14:21:27.730 回答
0

在我看来,在某些情况下用索引替换指针的解决方案会很慢。

  • 如果我们不删除任何点,point_id 将表示他点的索引,例如。节点[poin_id],没关系。

  • 但是如果我们删除列表中的任何点,point_id 将不会代表它在列表中的索引。我们将不得不使用 std::find 并获取找到点的 point_id。这大大降低了代码的速度......

  • 如果我们删除任何点,我们可以重新索引点列表以避免上述问题。但是我们不必忘记重新索引所有经络开始/结束索引......但这需要一些时间并且与问题中的复制构造函数相同。而且我认为,另一个类使用复制构造函数影响某个类的数据代表了数据结构的提议不是很合适......

于 2010-09-09T17:21:52.347 回答