我必须使用类似于电话簿的C ++应用程序:带有STL联系人列表的类议程。关于联系人层次结构,有一个名为Contact(一个抽象的)的基类,以及派生的class Friend and Acquainance(联系方式)。
例如,这些类具有一个名为getName的虚方法,它返回联系人的名称。
现在我必须通过添加另一种类型的联系人公司(来自联系人)实现复合模式,该公司还包含一组联系人(也是STL列表),可以是“叶子”类型(朋友或熟人),或者他们也可以是公司。
因此,公司是复合型。
问题是:如何以及在哪里可以实现STL find_if来搜索具有给定名称的联系人(通过getName函数或建议我使用其他方式)两者之间的“叶子”类型联系在公司集合内?
换句话说,如何使用统一的函数定义遍历树以便找到可能的匹配?
我希望我很清楚......
答案 0 :(得分:2)
嗯,一种方法:
virtual contact* contact::findContact(std::string name)
{
if(m_name == name) {return this;}
return NULL;
}
然后:
contact * Company::findContact(std::string name)
{
if(!contact::findContact(name) )
{
//For each contact in the contact list, findContact(name)
//If we find something, return that.
//Otherwise return null.
}
return this;
}
您正在做的是让每个节点找到您正在寻找的节点,而不关心它是什么类型的节点(叶子或其他)。然后,每个节点检查自己,对于那些有子节点的人,检查他们的孩子。
答案 1 :(得分:1)
列表是大型联系人的错误类型,因为您可能有O(N)来查找最后一个联系人,甚至找不到联系人。
我建议你使用哈希映射(来自boost / tr1的unordered_map)或常规地图,这样你就可以使用密钥通过ID或其名称找到它们。
听起来公司应该只是一个联系树
您可以找到树实现here
您通过树进行transVase以找到所需的节点。
答案 2 :(得分:0)
“现在我必须通过添加另一种类型的联系人,公司(来自联系人)来实现复合模式,该联系人还包含一组联系人(也是STL列表),它们可以是”叶子“类型(朋友或熟人),或者他们也可以是公司“
您可以为Company创建一个兼容stl的复合迭代器。
class Company : public Contact {
std::list<Contact *> contactList;
//snip...other private members
friend class CompanyIterator;
friend class ConstCompanyIterator;
public:
// nested iterator classes
class CompanyIterator : public std::iterator<std::forward_iterator_tag, Contact *> {
friend class Company;
// pair<>.first is the iterator obtain by calling begin()
// pair<>.second is the end iterator
std::stack< std::pair< std::list<Contact *>::iterator,
std::list<Contact *>::iterator> > iters_stack;
Contact *pCurrentContact;
Company *pCompany; // This is the top level company which will be iterated.
public:
explicit CompanyIterator(Company &c);
// Required forward iterator methods follow
CompanyIterator();
CompanyIterator(const CompanyIterator&);
CompanyIterator& operator=(const CompanyIterator& other);
Contact &operator*() const;
Contact *operator->() const;
CompanyIterator& operator++();
CompanyIterator operator++(int);
bool operator==(const CompanyIterator& x) const;
bool operator!=(const CompanyIterator& x) const;
};
// nested iterator class
class ConstCompanyIterator : public std::iterator<std::forward_iterator_tag,
const Contact *> {
friend class Company;
// We use CompanyIterator to implement ConstCompanyIteraor
CompanyIterator inner_iter; // fwd operations here,
// using "const_cast<Company *>(this)->method()"
public:
explicit ConstCompanyIterator(const Company & dir);
// This ctor will function as a cast operator, to convert a CompanyIterator
// into a ConstCompanyIterator
ConstCompanyIterator(const CompanyIterator &iter);
// Required forward iterator methods follow
ConstCompanyIterator();
ConstCompanyIterator(const ConstCompanyIterator&);
ConstCompanyIterator& operator=(const ConstCompanyIterator& other);
const Contact &operator*() const;
const Contact *operator->() const;
ConstCompanyIterator& operator++();
ConstCompanyIterator operator++(int);
bool operator==(const ConstCompanyIterator& x) const;
bool operator!=(const ConstCompanyIterator& x) const;
};
typedef CompanyIterator iterator;
typedef ConstCompanyIterator const_iterator;
iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;
// snip... other Company public methods
};
对于上面给出的前向迭代器方法的实现,请参阅Github上的Composite Iterator代码。大多数实现都在Directory.cpp中。 github代码用于模拟文件系统的复合模式。类目录是复合。类文件是叶类。类Node是基本组件类。
find_if的仿函数看起来像
FindIfFunctor {
std::string name;
public:
FindIfFunctor(const std::string& n) : name(n) {}
bool operator()(const Contact& c) { return c.getName().compare(name); }
};
最后,find_if代码
Company c;
// snip... stuff gets added to company
string someName("IBM");
find_if(c.begin(), c.end(), FindIfFunctor(someName));