4.6.1 实现更加困难
效率通常都会制约程序库实现的容易程度。譬如,更高效的Graph类的设计要求我们:设计、实现和测试Incedges类-而这些都是额外的工作,因为如果我们使用Set类,我们就不需要做这些工作。而且,使用Incedges类取代Set类来实现Node类,将要求程序库其余的接口实现都发生相应的修改:
- template<class T>
- class Node {
- public:
- bool is_adjacent(Node<T>* n) const;
- //...
- };
如果节点n和给定的节点(*this,即调用is_adjacent函数的节点对象)是连接的(就是指由一条边连接起来),那么is_adjacent函数将返回true。
在用Set类实现的Node类版本里,函数is_adjacent的实现是很容易的;如果operator*是Set类的交集运算符,我们就可以写出下面这个只有一行代码实体的函数:
- template<class T>
- bool Node<T>::is_adjacent(Node<T>*n) const {
- return !(incedges * n->incedges).is_empty();
- }
上面的代码测试两个集合的交集是否为空集。
假设Incedges类并没有提供集合的交集运算符;那么对于使用Incedges类的Node类版本,实现is_adjacent函数将会更加困难。下面是首次编写的代码,部分内容使用了伪代码:
- template<class T>
- bool Node<T>::is_adjacent (Node<T>* n) const {
- for(Edgebase* e in incedges)
- if(e Connect n and this node)
- return true;
- return false;
- }
在上面这个实现里,我们必须迭代整个入射边集合,检查节点n是否在某些连接边上面(在实际的代码中,Incedges类的迭代应该使用某些迭代器类来实现)。而且,虽然上面的伪代码是正确的,但它可能并不是最高效的实现。我们还可以使用下面更高效的方法:与其只迭代(循环)this节点所连接的边列表,还不如迭代this节点和n节点中所连接边数较少的列表:- template<class T>
- bool Node<T>::is_adjacent(Node<T>*n) const {
- Node<T>* sparser_node = this;
- if(n->incedges.size() < incedges.size())
- sparser_node=n;
- for(Edgebase* e in sparser_node->incedges)
- if(e connect n and this node)
- return true;
- return false;
- }
显然,与使用Set类实现的只有一行代码实体的is_adjacent函数相比,这个版本的is_adjacent函数的实现和使用都要困难得多。