基本设置是,假设我们有两个简单的类:
class User {
private:
int id;
public:
User(int id){ this->id = id };
};
class Channel {
private:
std::string name;
public:
Channel(std::string name) { this->name = name };
};
这两个类应该相互之间存在多对多关系,例如每个User
可以加入许多Channel
,每个Channel
可以拥有许多User
。
Channel
个对象的数量-数百个。 User
个对象的数量-数万个。
任务制定::给定一个特定的Channel
对象,我必须找到一个与它无关的User
。
问题:
1)考虑到给定的任务,这种多对多关系的最佳实现是什么?除了针对所有关系的直接迭代之外,是否有针对这种问题的特定算法?
2)如果关系应该具有一些其他属性,例如是否存储User
加入Channel
的时间?
我的想法:第一个想法是创建一些其他类,例如
class UserChannelRel {
private:
User* userPtr;
Channel* chPtr;
float timeJoined;
public:
UserChannelRel(User* user, Channel* channel, float tm) {
this->userPtr = user;
this->chPtr = channel;
this->timeJoined = tm;
}
};
并将它们存储在某个大的标准容器中(向量?)。但是然后遍历所有元素似乎很慢。
答案 0 :(得分:4)
首先,您可以创建两个存储库,以在一侧保留用户的完整列表,在另一侧保留频道的完整列表。通常,您可以使用maps:
map<int, User> users;
map<std::string, Channel> channels;
然后,我建议为每个频道吸引set个用户:
class Channel {
private:
std::string name;
std::set<int> subscribers;
public:
Channel(std::string name):name(name) { };
void add(int userid) {
subscribers.insert(userid);
}
};
然后要查找与某个频道无关的用户,您可以遍历这些用户并轻松检查该频道中是否包含该用户。
或者,您也可以使用全局用户集(或者与存储库同时维护集成员身份,或者由creating the set from the map来维护),并使用set_difference()
生成不属于用户的用户集。订阅者。
Example of use of set_difference
:
set<int> a { 1,2,3,4,5,6,7}; // imagine a set of all the users
set<int> b{ 2,3,8}; // imagine a set of the subscribers of a channel
vector<int> c; // container with the users who are not subscribers
set_difference(a.begin(),a.end(), b.begin(), b.end(), back_inserter(c));
copy(c.begin(), c.end(), ostream_iterator<int>(cout," "));
如何在两种方法之间进行选择?第一种方法(迭代和检查)具有快速找到第一个用户并开始对提案进行处理的优势。通过利用对集合和映射进行排序的事实,可以优化迭代。您无需查找所有用户。第二种方法很优雅,但是由于用户群庞大,可能需要花费更多时间,因为在执行任何操作之前都需要获得完整的结果。
答案 1 :(得分:0)
也许您可以尝试使用std::shared_ptr
?
每个User
到它们加入的shared_ptr
会有一组Channels
,这可以节省内存,因为一个Channel
可以由多个用户加入。
您可以执行同样的操作将Users
存储在Channels
中。
然后,您可以将Users
放在vector
中,并使用某种排序方式(例如合并等高效方式,尝试对现有的现有排序方式进行基准测试),以查看{{ 1}}的指针指向您正在查看的User
。