【发布时间】:2014-03-26 02:42:28
【问题描述】:
在计算机编程的艺术,生成所有组合的草案第 7.2.1.3 节中,Knuth 介绍了用于生成 Chase 序列的算法 C。
他还提到了一个类似的算法(基于以下等式)在没有源代码的情况下使用索引列表(草案的练习 45)。
我终于搞定了一个我觉得很丑的 c++ 版本。生成所有C_n^m组合,内存复杂度约为3(m+1),时间复杂度为O(m n^m)
class chase_generator_t{
public:
using size_type = ptrdiff_t;
enum class GET : char{ VALUE, INDEX };
chase_generator_t(size_type _n) : n(_n){}
void choose(size_type _m){
m = _m;
++_m;
index.resize(_m);
threshold.resize(_m + 1);
tag.resize(_m);
for (size_type i = 0, j = n - m; i != _m; ++i){
index[i] = j + i;
tag[i] = tag_t::DECREASE;
using std::max;
threshold[i] = max(i - 1, (index[i] - 3) | 1);
}
threshold[_m] = n;
}
bool get(size_type &x, size_type &y, GET const which){
if (which == GET::VALUE) return __get<false>(x, y);
return __get<true>(x, y);
}
size_type get_n() const{
return n;
}
size_type get_m() const{
return m;
}
size_type operator[](size_t const i) const{
return index[i];
}
private:
enum class tag_t : char{ DECREASE, INCREASE };
size_type n, m;
std::vector<size_type> index, threshold;
std::vector<tag_t> tag;
template<bool GetIndex>
bool __get(size_type &x, size_type &y){
using std::max;
size_type p = 0, i, q;
find:
q = p + 1;
if (index[p] == threshold[q]){
if (q >= m) return false;
p = q;
goto find;
}
x = GetIndex ? p : index[p];
if (tag[p] == tag_t::INCREASE){
using std::min;
increase:
index[p] = min(index[p] + 2, threshold[q]);
threshold[p] = index[p] - 1;
}
else if (index[p] && (i = (index[p] - 1) & ~1) >= p){
index[p] = i;
threshold[p] = max(p - 1, (index[p] - 3) | 1);
}
else{
tag[p] = tag_t::INCREASE;
i = p | 1;
if (index[p] == i) goto increase;
index[p] = i;
threshold[p] = index[p] - 1;
}
y = index[p];
for (q = 0; q != p; ++q){
tag[q] = tag_t::DECREASE;
threshold[q] = max(q - 1, (index[q] - 3) | 1);
}
return true;
}
};
有没有更好的实现方式,即在相同的内存下运行得更快或在相同的速度下使用更少的内存?
【问题讨论】:
-
经过非常简短的搜索后,我真的无法在网络上找到关于 Chase 序列的良好定义。但我发现了您可能感兴趣的代码:wiki.call-cc.org/Chase%20Sequence
-
@justhalf 谢谢,但它实际上是算法 C。
-
似乎应该有一个只使用索引数组和一个迭代器的解决方案。