对图表的教学方式提出疑问

发布于 2024-10-09 05:48:45 字数 498 浏览 6 评论 0原文

我来自阿根廷,但我想每个上过数据结构课的人都知道图是什么。如果您这样做,您可能知道哪种实现是“通用”或“标准”。可以通过List,或者数组来实现。甚至维基百科也这么说。还有马克·艾伦·韦斯、布鲁诺·普莱斯和路易斯·乔亚内斯·阿吉拉尔。

问题是。没有人想过这不是一种好方法吗?最推荐的方法是通过列表。但考虑到顶点之间只能有一条边,我不认为列表是执行此操作的良好界面。我的意思是,如果顶点 V1 与顶点 V2 连接,则只有一条边。

您不认为这将是一个集合而不是列表吗?

Class Vertex{
    private Set edges;
    private Object data;

    /** Methods**/
}

只是想知道一些意见,你怎么看?

谢谢!!

编辑: 另外,如果我们认为 Graph 不能有重复的元素,那么 HashSet 将是一个不错的选择,可以最大限度地减少插入中顶点的查找。

I'm from Argentina, but i think everybody who has ever take a Data Structures class know what a graph is. If you do, you might know what kind of implementations are "common" or "standar". It can be implemented through a List, or an array. Even Wikipedia says this. As well as Mark Allen Weiss, Bruno Preiss and Luis Joyanes Aguilar.

The thing is. No one ever has think that this is not a good way to do it? The most recommended way is through a List. But considered that vertices can have just one edge between them, i don't think that a List is the good interface to do this. I mean, if the Vertex V1 is connected with Vertex V2, then there is just one and only one edge.

Don't you think it would be a Set instead of a list?

Class Vertex{
    private Set edges;
    private Object data;

    /** Methods**/
}

Just want to know some opinions, what do you think?

Thanks!!

Edit:
Also, if we think that the Graph can't have repeated elements, a HashSet would be a good choice to minimize the lookup of the vertex in the insertion.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(3

半仙 2024-10-16 05:48:45

您正确地指出,顶点的邻接是通过集合(或者在多重图的情况下,多重集)来最准确地建模的。那么为什么数据结构书籍会写数组和链表呢?我可以想到三个原因:

  1. 编程语言应该包含集合作为原始数据类型的想法是相当新的。年长的作者不会考虑使用它,而现代的作者则倾向于遵循该领域的传统。

  2. 数据结构课程的目的之一是让您能够在低(具体)级别和高(抽象)级别思考数据的表示。集合是一种抽象数据类型,它(与链表和数组不同)没有明显的低级实现:有些集合最好表示为链表,有些集合为哈希表,有些集合为数组,等等。因此,数据结构课程很自然地会跳过集合的高级表示而转向其低级实现,无论如何您都必须了解这些实现,以便分析使用它们的算法的行为。

  3. 重要的是不要对如何表示数据类型教条,因为使用特定的表示可以最有效地表达算法。示例 1. 要计算图中每对顶点之间长度为 n 的路径,请用图的邻接矩阵表示该图,并将该矩阵求 n 次幂。如果您坚持将顶点的邻接表示为一组边,那么您将错过此算法(可以使用标准技术进行并行化)。示例 2. Knuth 针对精确覆盖问题的“Dancing Links”算法表示使用双向链表,以便可以重用已删除项目的链接以进行有效的回溯。

You're right to point out that the adjacencies for a vertex are most accurately modelled by a set (or in the case of a multigraph, a multiset). So why do data structures books write about arrays and linked lists instead? I can think of three reasons:

  1. The idea that programming languages should include sets as a primitive data type is fairly recent. Older writers wouldn't have considered using it, and modern writers tend to follow the traditions of the field.

  2. One of the purposes of a data structures course is to enable you to think about the representation of data at a low (concrete) level as well as at a high (abstract) level. A set is an abstract datatype that (unlike linked lists and arrays) doesn't have an obvious low-level implementation: some sets are best represented as linked lists, some as hash tables, some as arrays, and so on. So it is natural for a data structures course to skip over the high level representation of sets to their low-level implementation, which you have to know about anyway in order to analyse the behaviour of algorithms that use them.

  3. It's important not to be dogmatic about how to represent datatypes, because algorithms can be most efficiently expressed using particular representations. Example 1. To count the paths of length n between each pair of vertices in a graph, represent the graph by its adjacency matrix and raise the matrix to the power n. If you insist on representing the adjacencies of a vertex as a set of edges, then you'll miss this algorithm (which can be parallelized using standard techniques). Example 2. Knuth's "Dancing Links" algorithm for the exact cover problem represents sets of columns using doubly linked lists, so that the links from deleted items can be reused for efficient backtracking.

一身软味 2024-10-16 05:48:45

在相对较高的 C/C++ 程序员级别,图/网络的实现方式在很大程度上取决于对其执行的操作。作为一个 OR 人,我在这里的回答/例子可能有偏见。可以在图/网络上实现的一些最有效的算法是多项式时间算法。我能想到的大多数(如果不是全部)多项式时间算法(Dijkstra 的最短路径问题、运输问题、最大流问题等)都是最小成本流 (MCF) 问题的特殊情况。在计算上,解决 MCF 问题的最有效方法之一是通过网络单纯形算法(其本身是解决一般线性程序的单纯形算法的特化)。

在网络单纯形算法中,需要有效地表示生成树(在节点集上)。为了在图中表示生成树,可以使用多种数据结构。其中包括以下节点长度

predecessor[], thread[] and depth[] arrays.

在我遇到的网络单纯形算法的最有效实现中,这些并不表示为数组,而是通过我不确定的某种动态创建的内存块

calloc(number_of_nodes, sizeof(struct vertex));

(相对较低级别)编译器内部的内存分配是如何实现的 - 无论是列表/集合/映射。

因此,总而言之,实现图的最佳方法高度依赖于对其执行的操作。

网络单纯形算法以及高效实现该算法所需的数据结构可以在本书中找到。

At a relatively higher C/C++ programmer level, how a graph/network is implemented depends quite heavily on what operations are performed on it. Being an OR person myself, I am probably biased in my response/example here. Some of the most efficient algorithms that can be implemented on graphs/networks are polynomial-time algorithms. Most, if not all, polynomial-time algorithms I can think of (Dijkstra's shortest path problem, transportation problem, max-flow problem, etc.) are special cases of the minimum-cost-flow (MCF) problem. Computationally, one of the most efficient ways of solving an MCF problem is via the network-simplex algorithm (which in itself is a specialization of the simplex algorithm to solve a general linear program).

In the network-simplex-algorithm, a spanning tree (over the set of nodes) needs to be efficiently represented. To represent a spanning tree in a graph, a variety of data structures can be used. These include the following node-length

predecessor[], thread[] and depth[] arrays.

In the most efficient implementations of network-simplex-algorithms that I have come across, these are not represented as arrays but some sort of dynamically created block of memory via

calloc(number_of_nodes, sizeof(struct vertex));

I am unsure (at a relatively lower level) internal to the compiler what/how this memory allocation is implemented - whether it is a list/set/map.

So, in summary, the best way to implement a graph is highly dependent on the operations to be performed on it.

Network simplex algorithm and the data structures needed to efficiently implement the same can be found in this book.

聚集的泪 2024-10-16 05:48:45

从最抽象的角度来看,集合有一个谓词来测试某个元素是否在集合内。它还可以支持提供并集和交集的运算符。差异不一定是可计算的。

从最抽象的角度来看,List 支持迭代、子列表和追加。

大多数图算法都要求您迭代边缘,因此支持迭代的结构是首选。大多数算法不会尝试将相同的边添加两次,因此不需要删除重复项。

当然,库中的大多数集合都是有限的、可扩展的集合,它们也支持迭代,因此您可以使用它们,尽管您仍然需要检查重复项的成本。

一些基于图的系统确实使用集合作为底层机制,但它们处理的是无限图而不是有限图,在有限图中内涵集变得有用。

At its most abstract, a Set has a predicate to test whether an element is within the set. It may also support operators which provide union and intersection. Difference is not necessary computable.

At its most abstract, a List supports iteration, sub-list, and append.

Most algorithms on graphs require you to iterate over the edges, so a structure which supports iteration is preferred. Most algorithms do not attempt to add the same edge twice, so removal of duplicates is not required.

Of course, most sets in libraries are finite, extensional sets which also support iteration, so you could use them, though you would still have the cost of checking for duplicates.

Some graph based systems do use sets as the underlying mechanism, but they are dealing with infinite graphs rather than finite ones, where intensional sets become useful.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文