Но в этом случае я дублирую много информации на карте, и размер взорвется. Любая другая хорошая структура данных, которая компактна и также поддерживает быстрый поиск?
Вместо того, чтобы отображать элементы непосредственно в группы, вы можете ввести дополнительный уровень косвенности, чтобы покончить с этим дублированием, отображая элементы, которые std::string
с, идентификаторы группы , которые являются индексами. Затем вы можете сохранить std::vector
групп. Вы используете идентификаторы групп, полученные сопоставлением, чтобы индексировать этот вектор групп.
В качестве примера реализации этой идеи:
#include <unordered_map>
#include <unordered_set>
#include <string>
#include <vector>
class GroupRelation {
std::unordered_map<std::string, group_id_t> elem2group_id_;
std::vector<std::unordered_set<std::string>> groups_;
public:
using group_id_t = size_t;
auto num_groups() const { groups_.size(); }
auto add_group(std::unordered_set<std::string> group) {
auto grp_id = groups_.size();
for (auto const& elem: group)
elem2group_id_[elem] = grp_id;
groups_.push_back(std::move(group));
return grp_id; // return group_id_t of just added group
}
// for checking whether or not an element is in a group
bool is_in_group(const std::string& elem) const {
auto it = elem2group_id_.find(elem);
return elem2group_id_.end() != it;
}
// returns the group ID where the element belongs
group_id_t group_id(const std::string& elem) const {
auto it = elem2group_id_.find(elem);
return it->second;
}
const std::unordered_set<std::string>& group(group_id_t group_id) const {
return groups_[group_id];
}
std::unordered_set<std::string>& group(group_id_t group_id) {
return groups_[group_id];
}
};
Извлечение идентификатора группы из элемента может быть выполнено в среднем за постоянное время.
Пример использования:
auto main() -> int {
GroupRelation grp_rel;
grp_rel.add_group({"a", "b", "c"});
grp_rel.add_group({"e", "f", "g"});
for (auto const& elem: grp_rel.group(0))
std::cout << elem << ' ';
std::cout << '\n';
for (auto const& elem: grp_rel.group(1))
std::cout << elem << ' ';
std::cout << '\n';
}
Мой вывод:
b c a
g f e