无穷序列千奇百怪,常见的却寥寥可数.除自然数序列与斐波那契序列外,以下两个序列十分常见:
- 循环序列: 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点:
- 一定要有意识地区分摇摆序列与循环序列
- 一个摇摆序列由4个参数唯一确定: 左端点,右端点,初值,初始方向
- 生成下一个摇摆序列中的元素之前,一定要用**两个**if语句判明方向