C ++使用std :: list of pointers重新排序std :: vector元素

时间:2011-07-31 23:25:44

标签: c++ list pointers vector

当我试图写出一个新算法来重新排序std :: vector中的元素时,我遇到了这个问题。基本的想法是我有std :: list指向std :: vector的列表,其方式是*list.begin() == vector[0]*(++list.begin()) == vector[1]等等。 但是,对列表元素位置的任何修改都会破坏映射。 (包括附加指针)当映射被破坏时,列表的元素可以是随机顺序,但它们仍指向向量上的正确元素。任务是重新排序向量中的元素以纠正映射。

最简单的方法(我现在怎么做):

  • 创建新的空std :: vector并将其大小调整为与旧向量相等的大小。
  • 遍历列表并从旧向量中读取元素并将其写入新向量。将指针设置为指向新向量的元素。
  • 交换向量并释放旧向量。

遗憾的是,只有当我需要更多的矢量容量时,该方法才有用。当保持元素的当前向量具有足够的容量来存储所有传入元素时,效率很低。列表中的附加指针将指向不同的向量的storgate。简单的方法适用于此,因为它只从指针读取。

所以我想使用恒定的内存量来重新排序矢量“就地”。任何未指向当前向量的storgate的指针都会移动到指向当前向量的storgate。元素是简单的结构。 (POD中) 我有空的时候会尝试发布示例代码..

我该怎么做才能做到这一点?我已经完成了基本的想法,但我不确定是否有可能以恒定的内存量进行重新排序。


PS:我很抱歉帖子中的(可能)错误的语法和拼写错误。我希望它仍然可读。 :)

1 个答案:

答案 0 :(得分:2)

首先,为什么你有一个指针列表?您也可以将索引保存到矢量中,您可以将其计算为std::distance(&v[0], *list_iter)。所以,让我们首先建立一个索引向量,但你可以很容易地适应它直接使用你的列表:

std::vector<T> v;        // your data
std::list<T*> perm_list; // your given permutation list
std::vector<size_t> perms;

perms.reserve(v.size());
for (std::list<T*>::const_iterator it = perm_list.begin(), end = perm_list.end(); it != end; ++it)
{
  perms.push_back(std::distance(&v[0], *it));
}

(可能有一种方法可以使用std::transformstd::bind或lambdas在一行中执行此操作。)

现在要做的工作。我们只是使用置换的循环分解,并在我们进行时修改perms向量:

std::set<size_t> done;

for (size_t i = 0; i < perms.size(); while(done.count(++i)) {})
{
  T tmp1 = v[i];
  for (size_t j = perms[i]; j != i; j = perms[j])
  {
    T tmp2 = v[j];
    v[j] = tmp1;
    tmp1 = tmp2;

    done.insert(j);
  }
  v[i] = tmp1;
}

我正在使用辅助集done来跟踪哪些索引已被置换。在C ++ 0x中,您可以在任何地方添加std::move以使其与可移动容器一起使用。