無窮序列千奇百怪,常見的卻寥寥可數.除自然數序列與斐波那契序列外,以下兩個序列十分常見:
- 循環序列: 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語句判明方向