来回遍历数组
Go through the array back and forth
我们有一个长度为 3 的数组和一些计数序列:0,1,2,3,4,...
到无穷大。从该输入序列中,我们需要生成将来回遍历数组的序列,例如:0,1,2,1,0,1,2,1,0,...
等等 length=3
.
我认为这个任务在很多编程书籍中都是很常见的任务,但是我找不到标准的解决方案,所以我创建了自己的解决方案。有没有其他更有效和优雅的解决方案,因为我不喜欢我的解决方案???
#define LENGTH 5
int main()
{
char arr[LENGTH] = {'a','b','c','d','e'};
int i;
int base=0;
for(i=0;i<100;i++){
if(i%(LENGTH-1)==0){
if(base==0) base=LENGTH-1;
else base =0;
}
int j = abs(base-i%(LENGTH-1));
printf("%c ",arr[j]);
}
}
Java 代码(为方便起见):
public static void traverse(){
char arr[] = {'a','b','c','d','e'};
int base=0;
for(int i=0;i<100;i++){
if(i%(arr.length-1)==0){
if(base==0) base=arr.length-1;
else base =0;
}
int j = Math.abs(base-i%(arr.length-1));
System.out.println(arr[j]+" ");
}
}
也许是这样的:
#define LENGTH 5
int main()
{
char arr[LENGTH] = { 'a','b','c','d','e' };
int current = 0;
int direction = 1;
for (int i = 0; i < 100; i++)
{
printf("%c ", arr[current]);
if (current == 0)
direction = 1;
else if (current == LENGTH - 1)
direction = -1;
current += direction;
}
}
该解决方案仅从i
计算arr
的索引,从而避免需要保持任何状态(例如当前方向)。结果它有点复杂,但也适用于 i
.
的非连续值
char arr[] = { '0', '1', '2', '3', '4' };
const int LENGTH = sizeof arr / sizeof(*arr); // not necessary for char
assert(LENGTH > 1); // doesn't work for fewer than 2 elements
const int CYCLE = LENGTH - 1;
for (int i = 0; i < 100; ++i) {
printf("%c ", arr[ (i / CYCLE) & 1 ? CYCLE - i % CYCLE : i % CYCLE ]);
}
printf("\n");
说明:i / CYCLE
为数组循环的次数,& 1
检查该数的最低有效位来确定方向(奇数循环,该位为1向后, 偶数循环——从 0
开始——向前)。 i % CYCLE
是向前循环,但是由于CYCLE = LENGTH - 1
,它没有到达数组的最后一个索引。 CYCLE - i % CYCLE
为倒退循环,从CYCLE - 0
开始,也就是前进时最后一个没有到达的索引,到1
结束,这样就避免了重复索引0
] 再次前进时
换句话说,forward和backward循环都省略了一个索引,以避免在改变方向时重复,因此CYCLE = LENGTH - 1
,这也意味着LENGTH
必须至少是2
以避免被零除。
我们有一个长度为 3 的数组和一些计数序列:0,1,2,3,4,...
到无穷大。从该输入序列中,我们需要生成将来回遍历数组的序列,例如:0,1,2,1,0,1,2,1,0,...
等等 length=3
.
我认为这个任务在很多编程书籍中都是很常见的任务,但是我找不到标准的解决方案,所以我创建了自己的解决方案。有没有其他更有效和优雅的解决方案,因为我不喜欢我的解决方案???
#define LENGTH 5
int main()
{
char arr[LENGTH] = {'a','b','c','d','e'};
int i;
int base=0;
for(i=0;i<100;i++){
if(i%(LENGTH-1)==0){
if(base==0) base=LENGTH-1;
else base =0;
}
int j = abs(base-i%(LENGTH-1));
printf("%c ",arr[j]);
}
}
Java 代码(为方便起见):
public static void traverse(){
char arr[] = {'a','b','c','d','e'};
int base=0;
for(int i=0;i<100;i++){
if(i%(arr.length-1)==0){
if(base==0) base=arr.length-1;
else base =0;
}
int j = Math.abs(base-i%(arr.length-1));
System.out.println(arr[j]+" ");
}
}
也许是这样的:
#define LENGTH 5
int main()
{
char arr[LENGTH] = { 'a','b','c','d','e' };
int current = 0;
int direction = 1;
for (int i = 0; i < 100; i++)
{
printf("%c ", arr[current]);
if (current == 0)
direction = 1;
else if (current == LENGTH - 1)
direction = -1;
current += direction;
}
}
该解决方案仅从i
计算arr
的索引,从而避免需要保持任何状态(例如当前方向)。结果它有点复杂,但也适用于 i
.
char arr[] = { '0', '1', '2', '3', '4' };
const int LENGTH = sizeof arr / sizeof(*arr); // not necessary for char
assert(LENGTH > 1); // doesn't work for fewer than 2 elements
const int CYCLE = LENGTH - 1;
for (int i = 0; i < 100; ++i) {
printf("%c ", arr[ (i / CYCLE) & 1 ? CYCLE - i % CYCLE : i % CYCLE ]);
}
printf("\n");
说明:i / CYCLE
为数组循环的次数,& 1
检查该数的最低有效位来确定方向(奇数循环,该位为1向后, 偶数循环——从 0
开始——向前)。 i % CYCLE
是向前循环,但是由于CYCLE = LENGTH - 1
,它没有到达数组的最后一个索引。 CYCLE - i % CYCLE
为倒退循环,从CYCLE - 0
开始,也就是前进时最后一个没有到达的索引,到1
结束,这样就避免了重复索引0
] 再次前进时
换句话说,forward和backward循环都省略了一个索引,以避免在改变方向时重复,因此CYCLE = LENGTH - 1
,这也意味着LENGTH
必须至少是2
以避免被零除。