我正在开展一项与使用连续方法的电路测试相关的小型科学课程项目。该程序将解析电路定义文件,然后构建一个表示电路的易于修改的图形结构。然后对该图进行某些修改,并对其进行拓扑排序。排序后,图形将转换为由数组列表组成的静态结构,其中每个数组对应于某个拓扑排序程度。之后,可以轻松模拟电路,因为您可以依赖排序顺序并按顺序处理模型。
现在这一切都很好且合乎逻辑,但我提到的两个图是自定义数据结构,其中:
1)不是完全符合STL规范(无论如何对我来说都是漫长而艰难的 - 图形比矢量和列表更复杂)
2)对于第二张图,我假设它不可修改,并使用矢量矢量或矢量列表来提高速度。
3)我的图表可用的操作集是有限的,反映了我的项目的需求。
4)代码很简单。
现在我只是一名三年级的IT学生,在完成了软件设计课程并阅读了一些现实生活中的代码后,我想知道:
1)代码可以(甚至可以)简单吗?
2)在对数据结构做出假设时,我是否违反了数以千计的软件设计原则?
3)我是否真的总是符合我在此项目和未来项目中创建的所有数据结构的STL规范?
这个项目使用C ++。
感谢您的关注!我很欣赏这些问题的基本和理论答案,以及解决这个问题的实际方法的一个例子。
答案 0 :(得分:5)
1)代码可以(甚至可以)简单吗?
它不仅可以,它应该是。代码不需要复杂。
2)在对数据结构做出假设时,我是否违反了数以千计的软件设计原则?
嗯,你怎么能这样做。这个问题对我没有意义。3)我是否真的总是遵守我在此项目和未来项目中创建的所有数据结构的STL规范?
不。例如,如果您不需要迭代结构,请不要提供迭代器。只实现你真正需要的东西。
答案 1 :(得分:1)
我认为这样的简单设计没有错:
typedef int node_type; // or a more complex type here
typedef std::list<node_type> node_list;
typedef std::pair<node_list::const_iterator, node_list::const_iterator> edge_type;
typedef std::list<edge_type> edge_list;
struct graph
{
node_list nodes;
edge_list edges;
// Some member functions for doing specific things here
// for instance:
void remove_node(node_list::iterator i)
{
nodes.erase(i);
edges.remove_if(connects(i));
}
};
,其中
struct connects
{
connects(node_list::const_iterator i) : i(i) {}
bool operator()(const edge_type& e) const
{
return e.first == i || e.second == i;
}
private:
node_list::const_iterator i;
};
它保持简单,模块化,并允许您在其上使用标准库。它允许您迭代节点和边。如果你想要一个顶点的邻接列表,你将不得不遍历整个边缘列表,但这是设计的(如果你想快速做到这一点,你想要一个更好的结构)。
例如,定义(遗憾的是这不是标准的)
template <typename I, typename F, typename G>
F for_each_if(I first, I last, F f, G pred)
{
for ( ; first!=last; ++first ) if (pred(*first)) f(*first);
return f;
}
现在你可以做到
for_each_if(g.edges.begin(), g.edges.end(), something, connects(some_node));
迭代some_node
的邻接列表。
使用C ++ 0x,有更优雅的方法来编写这样的算法(使用lambdas)。