这个递归C代码是如何工作的?
有很多递归问题,我基本上了解一些简单的递归算法,比如数组元素和。但是,我的朋友给了我一个代码,它反转了一个数组:这个递归C代码是如何工作的?,c,recursion,C,Recursion,有很多递归问题,我基本上了解一些简单的递归算法,比如数组元素和。但是,我的朋友给了我一个代码,它反转了一个数组: void r(int a[], int s) { if(s <=2 ) return; int t = a[0]; a[0] = a[s-1]; a[s-1] = t; r(&a[1], s-2); // this line confused me, why &a[1] } void r(int a[],i
void r(int a[], int s)
{
if(s <=2 ) return;
int t = a[0];
a[0] = a[s-1];
a[s-1] = t;
r(&a[1], s-2); // this line confused me, why &a[1]
}
void r(int a[],int s)
{
如果(s需要了解的重要事情是a
是指向数组第一个元素的指针,那么a
与&a[0]
&a[1]
是指向数组第二个元素的指针。因此,如果使用&a[1]调用函数
作为其参数,它作用于从第二个元素开始的子数组。需要了解的重要一点是a
是指向数组第一个元素的指针,因此a
与&a[0]
&a[1]相同
是指向数组第二个元素的指针。因此,如果以&a[1]
作为参数调用函数,它将在以第二个元素开头的子数组上工作。&a[1]
相当于a+1
,即指向数组第二个元素的指针。函数调用将反转“中间”数组的s-2
元素。&a[1]
相当于a+1
,即指向数组第二个元素的指针。函数调用反转数组的“中间”s-2
元素。它与
void r(int *arr, size_t len)
{
for ( ; len >= 2; arr+=1,len-=2 ) {
int t = arr[0];
arr[0] = arr[len-1];
arr[len-1] = t;
}
}
,其中递归调用被循环替换。循环的“增量”部分(arr+=1,len-=2
)与递归调用的参数完全相同;结束条件(len>=2
)等同于递归停止符(这在原始中是错误的)。它与
void r(int *arr, size_t len)
{
for ( ; len >= 2; arr+=1,len-=2 ) {
int t = arr[0];
arr[0] = arr[len-1];
arr[len-1] = t;
}
}
,其中递归调用被循环替换。循环的“增量”部分(arr+=1,len-=2
)与递归调用的参数完全相同;结束条件(len>=2
)相当于递归停止符(在原始情况下是错误的)。必须使用以下参数调用函数:
- 指向数组第一个元素的指针。在C语言中,可以使用数组的名称来引用它
- 数组的大小
第一个“if”检查数组是否至少有两个元素。接下来,函数要做的是交换数组中第一个和最后一个元素的位置
递归调用更改下一步必须执行的边界。它将数组的开头增加一个位置,并将数组的结尾减少一个位置;因为这两个元素在此迭代中已反转。必须使用以下方法调用函数:
- 指向数组第一个元素的指针。在C语言中,可以使用数组的名称来引用它
- 数组的大小
第一个“if”检查数组是否至少有两个元素。接下来,函数要做的是交换数组中第一个和最后一个元素的位置
递归调用改变了下一步必须执行的边界。它将数组的开头增加一个位置,同时也将数组的结尾减少一个位置;因为这两个元素在这个迭代中被颠倒了。此算法背后的思想是在每一步:
-:要交换数组的最后一个a[s-1]
和第一个a[0]
元素,请执行以下操作:
int t = a[0];
a[0] = a[s-1];
a[s-1] = t;
-:和以递归方式交换中间位置:
r(&a[1], s-2);
要理解语法,请记住&a[n]
是给定数组的n+1
第个元素的地址。如果有int*b=&a[1]
,则b[0]==a[1]
,b[1]==a[2]
,等等
因此:
&a[1]
指从数组a
的第二个元素开始的数组
s-2
意味着递归传递的数组长度缩短了2个元素
如果您有一个数组[1 2 3 4 5 6 7 8 9 10]
,下面是递归过程中发生的情况:
[1 2 3 4 5 6 7 8 9 10] // r(&a[0], 10)
10 [2 3 4 5 6 7 8 9] 1 // r(&a[1], 8
10 9 [3 4 5 6 7 8] 2 1 // r(&(&a[1])[1], 6)
10 9 8 [4 5 6 7] 3 2 1 // r(&(&(&a[1])[1])[1], 4)
10 9 8 7 [5 6] 4 3 2 1 // r(&(&(&(&a[1])[1])[1])[1], 2)
很酷的是,该分析向我们展示了终止条件s该算法背后的思想是在每一步:
-:要交换数组的最后一个a[s-1]
和第一个a[0]
元素,请执行以下操作:
int t = a[0];
a[0] = a[s-1];
a[s-1] = t;
-:和以递归方式交换中间位置:
r(&a[1], s-2);
要理解语法,请记住&a[n]
是给定数组的n+1
第个元素的地址。如果有int*b=&a[1]
,则b[0]==a[1]
,b[1]==a[2]
,等等
因此:
&a[1]
指从数组a
的第二个元素开始的数组
s-2
意味着递归传递的数组长度缩短了2个元素
如果您有一个数组[1 2 3 4 5 6 7 8 9 10]
,下面是递归过程中发生的情况:
[1 2 3 4 5 6 7 8 9 10] // r(&a[0], 10)
10 [2 3 4 5 6 7 8 9] 1 // r(&a[1], 8
10 9 [3 4 5 6 7 8] 2 1 // r(&(&a[1])[1], 6)
10 9 8 [4 5 6 7] 3 2 1 // r(&(&(&a[1])[1])[1], 4)
10 9 8 7 [5 6] 4 3 2 1 // r(&(&(&(&a[1])[1])[1])[1], 2)
酷的是,这个分析告诉我们终止条件s简化了疯狂行走槽
void reverse(int a[], int s)
{
int temp; /* temporary value */
if (s <= 2) return; /* trigger done */
t = a[0]; /* temp = first index of a */
a[0] = a[s - 1]; /* a[0] = a[end - 1] (end including \0) */
a[s - 1] = t; /* a[end - 1] = temp */
r(&a[1], s - 2); /* pass address of a[1] and end - 2 */
}
我们得到;main()
调用reverse(ABCDEFG,7)
清单1
A
的地址引用被推送到堆栈(A{BCDEFG})
- 7被推到堆栈上
- 调用方的返回地址被推送到堆栈上
- 等等
- 调用的函数
什么的
#::::::::::::::::::::::::::::::::::::::::::::::::::::
reverse(ABCDEFG, 7); # Push to STACK 0xB (As List 1)
#====================================================
789abcd <- Memory address.
ABCDEFG <- Values.
0123456 <- Indexes for a in recursion 1.
if (7 <= 2) return;
temp = A
+ .
a[0] = a[6] => ABCDEFG = GBCDEFG
+
a[6] = temp => GBCDEFG = GBCDEFA
简化疯狂行走槽
void reverse(int a[], int s)
{
int temp; /* temporary value */
if (s <= 2) return; /* trigger done */
t = a[0]; /* temp = first index of a */
a[0] = a[s - 1]; /* a[0] = a[end - 1] (end including \0) */
a[s - 1] = t; /* a[end - 1] = temp */
r(&a[1], s - 2); /* pass address of a[1] and end - 2 */
}
我们得到;main()
调用reverse(ABCDEFG,7)
清单1
A
的地址引用被推送到堆栈(A{BCDEFG})
- 7被推到堆栈上
- 调用方的返回地址被推送到堆栈上
- 等等
- 调用的函数
什么的
#::::::::::::::::::::::::::::::::::::::::::::::::::::
reverse(ABCDEFG, 7); # Push to STACK 0xB (As List 1)
#====================================================
789abcd <- Memory address.
ABCDEFG <- Values.
0123456 <- Indexes for a in recursion 1.
if (7 <= 2) return;
temp = A
+ .
a[0] = a[6] => ABCDEFG = GBCDEFG
+
a[6] = temp => GBCDEFG = GBCDEFA
如果(s@wildplasser)你是绝对正确的,请参阅下面我的答案中的分析。如果(s@wildplasser)你是绝对正确的,请参阅下面我的答案中的分析。