摇摆序列

无穷序列千奇百怪,常见的却寥寥可数.除自然数序列与斐波那契序列外,以下两个序列十分常见:

  • 循环序列: 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语句判明方向
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值