接收不明确的规范时表示图的邻接表的数据结构

时间:2018-08-18 12:30:57

标签: c++ algorithm data-structures graph

我正在设计应基于图形的应用程序。 我不确定哪一种是在内存中表示图形邻接表的最佳方法。客户的要求非常模糊,因此我必须做一些假设。图的节点是一些ID,但是我不确定ID是否是顺序的。当涉及一般规格时,图论怎么说? 如果它们是顺序的,则节点数(N)也应限制最大ID,并且基本上可以确保ID覆盖区间 1,2…N 。请参阅下面的选项A。 如果它们不是顺序的,则ID可以从1跳到例如。 11,可能会跳过规范中的某些自然数。请参阅下面的选项B。 在ID旁边,还有一个c ++数据结构,我在其中存储多个信息(有效负载,连接的边等)。 我的算法还有两个选择:

A。将图形表示为向量,向量的索引将表示nodeID。

B。将图形表示为map,其中Node ID是键,而Data是存储值。

地图可以让我拥有随机ID,比如说输入数据是随机提供的。

文献(例如DFS,BFS或其他图形文章)主要考虑选项A,其中节点ID完全覆盖间隔 [1..N] 。我也会选择这个选项,因为它代表了一个公认的符号。 然后,将其添加到我的应用程序的“文档/前提条件”部分。

正确掩盖客户的歧义规格的最佳选择是什么?

4 个答案:

答案 0 :(得分:0)

您可以选择将图形表示为两个列出的选项的组合:具有包含两个成员的Node结构-整数label和您需要的另一个结构。

该图将存储一个std::vector<Node*> nodes;。但是,鉴于节点的标签与上面的向量中的位置不匹配的限制,您需要将标签和向量索引之间的对应关系存储在std::map<int, int> corresp;

鉴于此结构,如果您需要访问标签值为11的Node *,则可以执行Node* node = nodes[corresp[label]];

此外,标签可以是任何其他类型,例如std::string。唯一需要做的修改就是将映射的键类型更改为std::string

答案 1 :(得分:0)

情况1:顺序ID。然后,您可以按照索引对应于ID的方式将节点存储在数组中。

情况2:稀疏ID。

通常,图节点的表示允许它们具有有效负载(属性),例如ID。如果不需要按ID访问节点,则使用数组即可。

如果确实需要通过ID访问节点,请使用字典(映射)建立对应关系。您也可以将节点直接存储在字典中,但是节点枚举或排序会比较困难。

答案 2 :(得分:0)

我通常建议使用(可能是智能的)指针标识对象(如果它们是对象),因为C / C ++提供了这种机制来标识对象。

从根本上讲,您的图由许多节点和边组成,因此通常会出现以下情况:

public class OtherFragment extends Fragment {
    @Nullable
    @Override
    public View onCreateView(LayoutInflater inflater, @Nullable ViewGroup container, @Nullable Bundle savedInstanceState) {
        //just change the fragment_dashboard
        //with the fragment you want to inflate
        //like if the class is HomeFragment it should have R.layout.home_fragment
        //if it is DashboardFragment it should have R.layout.fragment_dashboard
        return inflater.inflate(R.layout.fragment_other, null);
    }
}

然后,在您的class Node { int id; Data data; std::vector<Node *> edges; } 类中,您将需要每种用于访问节点的 other 方式的映射。您可能需要能够按ID查找节点,因此图类将为此需要某种索引-密集ID为Graph或稀疏ID为vector<Node *> nodesById。选择哪个不应该是一个具有很多后果的重要决定。添加方法map<int,Node*> nodesById,然后可以随时更改表示形式。始终记住,在软件开发中,当一个决定没有明显的答案,或者当未来可能会改变最佳答案时,轻松改变主意比做出正确决定要好得多。选择

随着人们向您的图形添加需求,您可能需要以不同的方式访问节点,并且可能必须添加更多种类的索引来支持那些特定的用例。

您需要对图形执行的两个工作是构造和破坏。构造可能需要Node *getNodeById(int id)索引。销毁肯定需要某种方法来枚举所有节点,并且您为nodesById选择的任何表示形式也都足以满足要求。

答案 3 :(得分:0)

您可以使用向量图。像这样:

Map<int,vector<Node *>>;

此映射中的键将是您的节点ID。对应的向量具有第一个条目作为该特定ID的对应节点,然后具有该ID节点的所有边。

假设您的图有一个ID为2的节点,并且该节点的边为ID为3,4和6的节点。

因此,与地图中的键2对应的条目将是一个向量,其第一个条目作为ID为2的节点,然后其下一个条目作为ID 3的节点,然后为4,最后是节点6。

您的Node的每个矢量条目看起来都类似于此:

struct Node {
 int id,
 InfoData obj;
}