关于邻接矩阵实现的问题

Posted

技术标签:

【中文标题】关于邻接矩阵实现的问题【英文标题】:Question about adjacency matrix implementation 【发布时间】:2020-09-22 12:47:43 【问题描述】:

我在使用邻接矩阵的图形实现方面遇到问题。作为一个小背景,我必须从一个文件中读取每行包含一个演员、他们出演的电影以及制作年份的文件。我的工作是从文件中创建一个图表。然后,该图将由演员的顶点组成,这些演员的边缘关系是他们一起出演了同一部电影。在文件中,演员是顶点,电影和出版年份是边。 我找到了一种将顶点存储在 std::vector 中的方法,并且还创建了一个名为 MovieInformationstruct 来存储 string movieNameint movie year。这些也存储在vector< pair< int,MovieInformation>> 中。

但是,我不知道如何将信息插入vectors,以使演员和他们主演的电影的信息保持在一起。

来自文件的示例输入是:

亚历克斯·威尔 1984 年停止讲道理 史蒂文·斯卡尔斯 1984 年不再讲道理 鲁本·布莱兹无组织犯罪 1989 霍伊特阿克斯顿无组织犯罪 1989 Fred Gwynne 无组织犯罪 1989

而输出将是

(演员)--[电影#@year]-->(演员)--...

至于代码部分,除了上面的解释,没有太多写的。

【问题讨论】:

您至少需要发布到目前为止的代码。还有示例文件。 您还应该提供您希望成为您的程序结果的示例 我在上面更新了 pair 中的int 是什么?要将演员与电影联系起来,您可以将演员的姓名存储在结构中。那真的很简单,但不能很好地扩展。稍后,您可能需要一个演员表和对结构中演员表中演员条目的引用。尝试通过绘画来形象化这些关系。 是的 int 是用来确定两个顶点是否有共同的边使得 matrix[x][y] == 1 或 0 【参考方案1】:

首先,您需要简化顶点识别过程。我建议通过将它们存储在无序映射中来枚举它们,其中参与者名称作为字符串键,它们的相应索引作为值。这将产生O(1) 访问演员索引的预期时间。然后,您可以形成包含在同一部电影中出演的演员的索引的电影集。当然,您还必须考虑电影的年份,因为可以有两部名为M 的不同电影在不同年份上映。一旦你形成了这些集合,那么你就会知道对于对应于电影M 的集合sY 出现,s 中的所有顶点对在它们之间都有一条边。

枚举过程如下面的代码所示。

void populate(vector<string>& actorNames, unordered_map<string, int>& indexMap) 
    int nextIndexToAssign = 0;
    for(int i=0; i < input.size(); ++i) 
        if(indexMap.find(input[i]) == indexMap.end()) 
            indexMap[input[i]] = nextIndexToAssign++;
        
    

运行与上述实现类似的代码后,您可以通过indexMap[actorName] 访问演员的索引,其中actorName 是存储演员姓名的字符串变量。你可以对电影做类似的事情,其中​​的键是pair&lt;string, int&gt; 而不是string

枚举完成后,您可以使用sets的向量作为桶来存储曾出演过同一部电影的演员。

typedef pair< string, pair<string, int> > InputLine;
vector<InputLine> input; // defined somewhere, has size N
...

M = movieIndices.size();
vector< set<int> > actorsInMovie(M);
for(int i=0; i < N; ++i) 
    string& actor = input[i].first;
    string& movie = input[i].second;
    int actorIndex = actorIndices[actor];
    int movieIndex = movieIndices[movie];
    actorsInMovie[movieIndex].insert(actorIndex);

然后,您需要做的就是遍历 actorsInMovie 并为 actorsInMovie[i] 中的每一对索引 uv,在 uv 之间放置一条边。

请注意,以上代码未经测试,由于问题陈述中缺少任何源代码,仅用作伪代码。

考虑到有N 行输入,可以有O(N) 电影和O(N) 演员。有了这些信息,我们可以说枚举边(即电影和年份对)将花费O(N) 预期时间。此外,枚举每部电影并为每部电影形成一个集合将花费O(N) 预期时间。在所有演员都在同一部电影中的最坏情况下,形成图的边缘会花费O(N*N) 时间,因为您需要在所有O(N) 演员对之间设置一条边缘。总的来说,即使 unordered_map 的时间复杂度最差,在最坏的情况下,您最终也会得到 O(N*N) 的时间复杂度。

邻接矩阵的细节不会改变时间复杂度。你只需要用0初始化一个N x N矩阵adjacencyMatrix的所有单元格,表示ab之间没有任何顶点连接。然后你执行我上面介绍的枚举和分组(即集合)策略。最后,对于索引为ij 的每一对actor,您设置adjacencyMatrix[i][j] = adjacencyMatrix[j][i] = 1。整体时间复杂度仍为O(N*N)。并且由于您需要 O(N*N) 时间和空间复杂度来分配和填充 NxN 矩阵,因此这是您可能实现的最佳时间和空间复杂度,除非为您的用例提供任何其他详细信息/限制。

【讨论】:

您好,感谢您的指导,我真的很感激。但是,我有一个问题想知道我会存储演员的“索引”,这是什么意思,然后我如何比较同一部电影中主演的演员的索引? @Freshzak187 我更新了我的答案,但是由于您没有在您的问题中分享任何实现尝试,我的代码示例应该只被视为通用伪代码。 感谢您的澄清。我会尝试并回复你

以上是关于关于邻接矩阵实现的问题的主要内容,如果未能解决你的问题,请参考以下文章

邻接矩阵的应用

邻接矩阵表示的无向图深度遍历实现

邻接矩阵表示的无向图深度遍历实现

c++利用邻接矩阵存储方法实现图的存储与输出。

求算法,用邻接矩阵和邻接表创建一个图,实现深度和广度搜索,菜单形式,c语言的代码。无向无权的图。

关于邻接矩阵的拆点 和一些杂七杂八想不到的做法