我正在尝试使用此处描述的方法实现左数组旋转:http://www.cs.bell-labs.com/cm/cs/pearls/s02b.pdf(在反转算法部分下)
当起始索引不为0时,我无法反转数组。
这是我到目前为止所做的:
void reverse_arr(int *a, int start, int end)
{
int i;
int len = end - start;
//printf("Len pre loop: %d\n", len);
int swap;
for(i = start; i < --len; i++)
{
//printf("start: %d\tlen: %d\n", start, len);
swap = a[i];
a[i] = a[len];
a[len] = swap;
}
}
当起始索引为0时,这很有效,但是当它是其他任何东西时,它永远不会反转所有元素。
前:
int test[] = {1,2,3,4,5,6};
reverse_arr(test, 0, 2); //reverse the first 2 elements of the array
结果为:{2,1,3,4,5,6}
预期
int test[] = {1,2,3,4,5,6};
reverse_arr(test, 2, 6); //reverse the last 4 elements of the array
导致:{2,1,4,3,5,6}
这是不期望的,只有3和4被逆转。
任何帮助都将不胜感激。
答案 0 :(得分:4)
您需要调整交换中的其他下标:
void reverse_arr(int *a, int start, int end)
{
int len = end - start;
for (int i = start; i < --len; i++)
{
int swap = a[i];
a[i] = a[i+len];
a[i+len] = swap;
}
}
你也可以使用:
void reverse_arr(int *a, int start, int end)
{
int len = end - start;
end--;
for (int i = start; i < --len; i++, end--)
{
int swap = a[i];
a[i] = a[end];
a[end] = swap;
}
}
#if defined(VERSION1)
static void reverse_arr(int *a, int start, int end)
{
int i;
int len = end - start;
int swap;
for (i = start; i < --len; i++)
{
swap = a[i];
a[i] = a[i+len];
a[i+len] = swap;
}
}
#else
static void reverse_arr(int *a, int start, int end)
{
int i;
int len = end - start;
end--;
for (i = start; i < --len; i++, end--)
{
int swap = a[i];
a[i] = a[end];
a[end] = swap;
}
}
#endif
#define DIM(x) (sizeof(x)/sizeof(x[0]))
#include <stdio.h>
static void print_array(int *array, size_t size)
{
for (size_t i = 0; i < size; i++)
printf(" %d", array[i]);
putchar('\n');
}
static void tester(int lo, int hi)
{
int test[] = {1,2,3,4,5,6};
printf("Before: (%d, %d)\n", lo, hi);
print_array(test, DIM(test));
reverse_arr(test, lo, hi); //reverse the first 2 elements of the array
printf("After: (%d, %d)\n", lo, hi);
print_array(test, DIM(test));
putchar('\n');
}
int main(void)
{
tester(0, 2);
tester(2, 6);
return(0);
}
使用-DVERSION1编译的结果是否相同:
Before: (0, 2)
1 2 3 4 5 6
After: (0, 2)
2 1 3 4 5 6
Before: (2, 6)
1 2 3 4 5 6
After: (2, 6)
1 2 6 4 5 3
答案 1 :(得分:3)
您应该完全放弃len
,而是使用end
。在您使用它时,您也可以放弃i
,然后使用start
。您的代码将以这种方式变得更具可读性:
void reverse_arr(int *a, int start, int end)
{
int swap;
while(start < end)
{
swap = a[start];
a[start++] = a[--end];
a[end] = swap;
}
}
答案 2 :(得分:1)
这是因为您将i
与len
进行比较,如果它从0开始就没有问题,但如果它从其他任何地方开始就没有(基数值不同)。
例如,如果要从偏移12开始旋转三个字符,则在退出状态下for
循环开始后不会发生任何事情。
快速解决方法是在开始循环之前简单地调整a
,以便它有效地认为(本地值)a
是数组的开头:
a += start;
for (i = start; i < --len; i++) // No change on this line.