我正在为我正在使用的C ++类进行图形实现。这是我到目前为止所提出的:
struct Edge {
int weight;
Vertex *endpoints[2]; // always will have 2 endpoints, since i'm making this undirected
};
struct Vertex {
int data; // or id
list<Edge*> edges;
};
class Graph {
public:
// constructor, destructor, methods, etc.
private:
list<Vertex> vertices;
};
此刻此刻有点粗糙,但我想我想知道......我错过了一些基本的东西吗?目前看起来有点太容易了,通常这意味着我设计错了。
我的想法是图形只是一个顶点列表,它有一个列表边缘,它有一个边缘列表,它有两个顶点端点。
除了一些函数我将放入图中(如:最短距离,大小,添加顶点等),我在这些结构/类的基本实现中遗漏了什么?
答案 0 :(得分:1)
有时你需要设计这样的东西,并不是很明显最有用的实现和数据表示是什么(例如,它是否更好地存储点集合,或边集合,或两者兼而有之?),你会一直遇到这种情况。
例如,您可能会发现您的第一个构造函数不是您真正想要的东西。使Graph类创建顶点而不是传入它们可能更容易。
不要在课堂内工作并玩猜谜游戏,而是先后退一步,先处理客户端代码。例如,您将要创建一个Graph对象,添加一些点,以某种方式连接带有边的点等。
您从客户端拨打电话的顺序将自然而然,功能本身的参数也将自然而然。通过了解客户端的外观,您可以开始自己实现这些功能,实际实现应该更加明显
答案 1 :(得分:1)
关于您的实施的评论:
图形是一组对象,其中一些对象是相关的。因此,您当前的实施是一种可行的方式;你建模对象及其之间的关系。
当前实现的优势主要在于沿边缘的恒定查找时间和普遍性。 查找时间:如果要访问节点k
的 n 邻居,可以在固定时间内完成。 概括性:这几乎代表了某人可以想到的任何图表,特别是如果您将weight
和data
的数据类型替换为对象(或Template) 。
您当前实现的缺点是它可能比理想慢。查看边缘将是便宜的,但仍然需要两个跃点而不是一个(节点 - >边缘 - >节点)。此外,使用边缘列表将花费您 O(d)时间来查找特定边缘,其中 d 是图形的度数。 (你对指针的依赖也要求图表适合一台计算机的内存;你的Facebook图表或美国公路网络都有问题。我怀疑并行计算是你现在关注的问题。)
实施图表时的担忧:
但是,您的问题是询问这是否是最佳方式。这是一个难题,因为图表的几个特定品质可以发挥作用。
边缘信息:如果顶点相关的方式无关紧要(即边缘没有重量或值),使用边缘对象几乎没有意义;这只会减慢你的速度。相反,每个顶点只能保留一个指向其邻居的指针列表,或者其邻居的ID列表。
构造:正如您在评论中注意到的那样,您当前的实现要求在添加边之前有一个顶点可用。总的来说这是事实。但是,您可能希望在添加边时动态创建顶点;这可以使构造看起来更干净,但如果顶点具有非恒定的查找时间将花费更多时间。如果在构建图形之前知道所有顶点,那么首先明确地创建它们然后是边缘可能是有益的。
密度:如果图形是稀疏的(即,每个顶点的边数近似恒定),则邻接列表也是一种好方法。但是,如果它很密集,如果使用adjacency matrix,通常可以提高性能。每个顶点按顺序保存所有其他顶点的列表,因此访问任何边是一个恒定时间操作。
算法:您计划在图表上解决哪些问题?根据图表的表示方式,多个famous graph algorithms的运行时间不同。
<强>附录:强>
请查看此问题以获取更多可能对您有所帮助的评论: Graph implementation C++