我是一名C程序员,并试图在C ++上做得更好。我想实现一个置换函数(不使用STL算法)。我提出了以下算法(我的C思维方式),但是
a) it crashes for k > 2 (I suppose because the element that the iterator
points to, gets deleted, is inserted back and then incremented).
b) erase/insert operation seem unnecessary.
你们中的C ++专家将如何实现它?
template <class T>
class Ordering {
public:
Ordering(int n);
int combination(int k);
int permutation(int k);
private:
set<T> elements;
vector<T> order;
}
template <class T>
int Ordering<T>::permutation (int k) {
if (k > elements.size()) {
return 0;
}
if (k == 0) {
printOrder();
return 1;
}
int count = 0;
for (typename set<T>::iterator it = elements.begin();
it != elements.end();
it++
)
{
order[k-1] = *it;
elements.erase(*it);
count += permutation(k-1);
elements.insert(*it);
}
return count;
}
答案 0 :(得分:0)
问题出在elements
集上的迭代中。您尝试增加已删除的迭代器。那不行。
如果您坚持使用此方法,则必须先存储it
的后继者,然后再调用set::erase
。这意味着您必须将for循环的增量部分移动到循环中。
像这样:
for (typename set<T>::iterator it = elements.begin();
it != elements.end();
/* nothing here */
)
{
order[k-1] = *it;
typename set<T>::iterator next = it;
++next;
elements.erase(*it);
count += permutation(k-1);
elements.insert(order[k-1]);
it = next;
}
修改:暂时从您的设置中“移除”对象的一种可能方法是拥有std::set<std::pair<T,bool>>
并简单地写it->second = false
,然后再写it->second = true
。然后,在迭代时,您可以跳过条目,其中第二个值为false
。这增加了一些开销,因为你必须在降序时做更多的工作。但是插入+删除元素每次都会增加对数开销,这可能更糟糕。
如果您使用(自定义)链接列表(也许您甚至可以std::list
这样做),您可以非常便宜地删除和重新插入对象。