搖擺序列

無窮序列千奇百怪,常見的卻寥寥可數.除自然數序列與斐波那契序列外,以下兩個序列十分常見:

  • 循環序列: 0, 1, 2, 3, 0, 1, 2, 3, 0, 1, 2, 3, …
  • 搖擺序列: 0, 1, 2, 3, 2, 1, 0, 1, 2, 3, 2, ,1, 0, …

對於循環序列,我們有很優雅的生成方式:

for(i = 0; ;++i)
    printf("%d, ", i%4);

但是對於搖擺序列,生成方式卻要複雜一些.例如,我們可以用下面的循環生成一個搖擺序列:

void swing(void) {
    int i = 0, d = 1;

    while (true) {
        printf("%d, ", i);
        getchar();
        if (i == 3)
            d = -1;
        else if (i == 0)
            d = 1;
        i += d;
    }
}

注意這裏不能將兩個if語句合爲一個,寫成這樣:

if (i == 0 || i == 3)
    d *= -1

因爲當你將這個函數的參數分離出來的時候,若給定初值爲0,d爲1,那麼這段代碼將會崩潰.

更一般地,可以將搖擺序列抽象成一個類:

struct Swinger {
    int left, rght;
    int curr, step;

    Swinger(void) {
        range(0, 0);
        ready(0, 0);
    }

    Swinger(const int left, const int rght, const int bgn=0, const int step=0) {
        range(left, rght);
        ready(bgn, step);
    }

    /** 設定搖擺範圍 */
    inline void range(const int left, const int rght) {
        this->left = left;
        this->rght = rght;
    }

    /** 設置搖擺的初值和方向 */
    inline void ready(const int bgn, const int step) {
        curr = bgn;
        this->step = step;
    }

    /** 取搖擺序列中的下一個值
     *
     * 必須設定好搖擺區間和搖擺的初值與方向
     */
    inline int next(void) {
        int res = curr;
        if (curr <= left)
            step = abs(step);
        else if (curr >= rght)
            step = -1 * abs(step);
        curr += step;
        return res;
    }

    /** 用搖擺序列填充一個數組 */
    void fill(int * const a, const int n, const int bgn, const int step) {
        ready(bgn, step);
        for (int i = 0; i < n; ++i)
            a[i] = next();
    }
};

然後,你可以用這種方式取調用這個類:

int main(void) {
    int a[100];
    Swinger swinger;

    swinger.range(0, 5);
    swinger.ready(0, -1);
    for (int i = 0; i < 100; ++i)
        printf("%d, ", swinger.next());
    printf("\n");

    swinger.range(0, 15);
    swinger.fill(a, 100, 0, 1);
    for (int i = 0; i < 100; ++i)
        printf("%d, ", a[i]);
    printf("\n");
}

值的注意的有3點:

  1. 一定要有意識地區分搖擺序列與循環序列
  2. 一個搖擺序列由4個參數唯一確定: 左端點,右端點,初值,初始方向
  3. 生成下一個搖擺序列中的元素之前,一定要用**兩個**if語句判明方向
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章