集合插入元素的向量

Vector of set insert elements

我正在尝试编写一个函数,它将 return 表示团队成员的集合类型字符串的向量。

一组名字应该被分类到一个游戏的团队中。团队的规模应该相同,但这并不总是可能的,除非 n 可以被 k 整除。因此,他们决定第一种模式(n,k)队有n/k+1人,其余队有n/k人。

#include <iostream>
#include <vector>
#include <string>
#include <set>
#include <list>
typedef std::vector<std::set<std::string>>vek;
vek Distribution(std::vector<std::string>names, int k) {
  int n = names.size();
  vek teams(k);
  int number_of_first = n % k;
  int number_of_members_first = n / k + 1;
  int number_of_members_remaining = n / k;
  int l = 0;
  int j = 0;
  for (int i = 1; i <= k; i++) {
    if (i <= number_of_first) {
      int number_of_members_in_team = 0;
      while (number_of_members_in_team < number_of_members_first) {
        teams[l].insert(names[j]);
        number_of_members_in_team++;
        j++;
      }
    }
    else {
      int number_of_members_in_team = 0;
      while (number_of_members_in_team < number_of_members_remaining) {
        teams[l].insert(names[j]);
        number_of_members_in_team++;
        j++;
      }
    }
    l++;
  }

  return teams;
}

int main ()
{
  for (auto i : Distribution({"Damir", "Ana", "Muhamed", "Marko", "Ivan",
                              "Mirsad", "Nikolina", "Alen", "Jasmina", "Merima"
                             }, 3)) {
    for (auto j : i)
      std::cout << j << " ";
    std::cout << std::endl;
  }
  return 0;
}

OUTPUT should be:

Damir Ana Muhamed Marko

Ivan Mirsad Nikolina

Alen Jasmina Merima

MY OUTPUT:

Ana Damir Marko Muhamed

Ivan Mirsad Nikolina

Alen Jasmina Merima

你能解释一下为什么名字没有按正确的顺序打印吗?

teams 作为 std::vector<...> 支持通过索引进行随机访问。
auto & team_i = teams[i]; (0 <= i < teams.size()),会给你一个向量的元素。 team_i 是对类型 std::set<std::list<std::string>> 的引用。

由于 std::set<...> 不支持通过索引进行随机访问,您需要通过迭代器(begin()end() 等)访问元素,例如:auto set_it = team_i.begin();*set_it 将是 std::list<std::string>.

类型

由于 std::list<...> 也不支持通过索引进行随机访问,因此您需要再次通过迭代器访问它,例如:auto list_it = set_it->begin();*list_it 将是 std::string.

类型

这样就可以访问向量中的每个集合、每个集合中的每个列表以及每个列表中的每个字符串(在将它们添加到数据结构之后)。

但是 - 在std::setstd::list中使用迭代器不如在std::vector中使用索引随机访问方便。 std::vector 有额外的好处(简单高效的实现,连续的内存块)。
如果您使用 std::vectors 而不是 std::setstd::listvek 将被定义为:

typedef std::vector<std::vector<std::vector<std::string>>> vek;

std::list 作为链表有一些好处(比如能够在 O(1) 中添加元素)。 std::set 保证每个值都出现一次。 但是,如果您真的不需要这些功能,如果您只使用 std::vector 作为容器,则可以使代码更简单(通常更高效)。

注意:如果每个集合只包含 1 个列表(字符串),您可以考虑去掉 1 级层次结构,即将列表(或我建议的向量)直接存储为 top-level 向量的元素。


更新:

由于问题已更改,这里有一个简短的更新:

  1. 在我上面的回答中,忽略所有提到的 std::list。所以当你迭代 set::set 时,元素已经是 std::strings.
  2. 名称与您预期的顺序不一致的原因: std::set 保持元素排序,当你迭代它时,你将按照该排序顺序获取元素。请在此处查看答案:Is the std::set iteration order always ascending according to the C++ specification?。您的集合包含 std::string,它们的默认排序顺序是按字母顺序排列。
    使用 std::vector 而不是我上面建议的 std::set ,将会得到你想要的结果(std::vector 不会自动排序)。

如果你只想尝试使用 std::vector:
vek 更改为:

typedef std::vector<std::vector<std::string>>vek;

并将 insert 的用法(将元素添加到集合中)替换为 push_back 以对矢量执行相同的操作。