2
在計算機編程領域的第7.2.1.3節草案中,生成所有組合,Knuth引入了用於生成Chase序列的算法C.如何生成Chase的序列
他也提到了類似的算法(根據下面的公式)和索引列表的工作沒有源代碼(草案行使45)。
我終於想出了一個C++版本我認爲這是相當難看。生成所有C_N^M組合,存儲複雜性是約3(M + 1)和時間複雜性爲O(MN^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;
}
};
沒有任何一個具有更好的實施方案,即有界跑得更快使用相同的內存或以相同的速度使用較少的內存?
經過非常簡短的搜索後,我無法真正在Web上找到Chase序列的良好定義。但我發現這個代碼可能是你的興趣:http://wiki.call-cc.org/Chase%20Sequence – justhalf
@justhalf謝謝,但它實際上是算法C. – cqdjyy01234
它似乎好像應該有一個解決方案,只使用索引數組和一個迭代器。 –