簡體   English   中英

如何生成大通的序列

[英]how to generate Chase's sequence

在計算機編程領域的草案第7.2.1.3節中,生成所有組合,Knuth引入了用於生成Chase序列的算法C。

算法C

他還提到了一種類似的算法(基於以下等式),該算法適用於沒有源代碼(草案的練習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;
    }
};

有沒有人有更好的實現,即在相同的內存下運行更快,或者在相同的速度下使用更少的內存?

我認為下面的C代碼更接近Knuth的想法。 毫無疑問,有一些方法可以使它變得更優雅(特別是,我會留下一些腳手架以防實驗失敗),盡管我懷疑可以處理數組w 如果存儲是出於某種原因真的很重要,然后盜取符號位a陣列。

#include <stdbool.h>
#include <stdio.h>

enum {
  N = 10,
  T = 5
};

static void next(int a[], bool w[], int *r) {
  bool found_r = false;
  int j;
  for (j = *r; !w[j]; j++) {
    int b = a[j] + 1;
    int n = a[j + 1];
    if (b < (w[j + 1] ? n - (2 - (n & 1)) : n)) {
      if ((b & 1) == 0 && b + 1 < n) b++;
      a[j] = b;
      if (!found_r) *r = j > 1 ? j - 1 : 0;
      return;
    }
    w[j] = a[j] - 1 >= j;
    if (w[j] && !found_r) {
      *r = j;
      found_r = true;
    }
  }
  int b = a[j] - 1;
  if ((b & 1) != 0 && b - 1 >= j) b--;
  a[j] = b;
  w[j] = b - 1 >= j;
  if (!found_r) *r = j;
}

int main(void) {
  typedef char t_less_than_n[T < N ? 1 : -1];
  int a[T + 1];
  bool w[T + 1];
  for (int j = 0; j < T + 1; j++) {
    a[j] = N - (T - j);
    w[j] = true;
  }
  int r = 0;
  do {
    for (int j = T - 1; j > -1; j--) printf("%x", a[j]);
    putchar('\n');
    if (false) {
      for (int j = T - 1; j > -1; j--) printf("%d", w[j]);
      putchar('\n');
    }
    next(a, w, &r);
  } while (a[T] == N);
}

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM