函数递归调用: 调用者 与 被调用者之间的四种数据传递关系
递归就是函数调用本身,来解决子问题,通过子问题的解构造本问题的解。
递归可以用于简化程序,让程序结构明了。。
调用者与被调用者之间有以下的四种数据传递关系:
1>没有任何数据传递
e.g. 打印链表
void PrintList(ListNode const *list)
{
if(list == NULL) return; //exit
cout << list->val << " ";
PrintList(list->next);
}2> 调用者 <= === 被调用者
这是我们通常习惯的数据传递(通过解决子问题,来解决本问题)
e.g. 计算阶乘
int f(int n)
{
if(n == 0 || n == 1) return 1;
return n * f(n-1);
}3> 调用者 = ===> 被调用者
其实我们从小学的数的加法运算就可以认为是这种情况。
115 + 126 = 241
低位运算结果(5+6=11)有进位,需要传递给被调用者
4> 调用者 <= ===> 被调用者
这个数据传递存在于那些子问题与本问题有相互的数据依赖性的时候。
给个例子,就会比较明了。
e.g. 用两个单链表表示两个非负整数,每个节点表示一个十进制位,整数反向存放。
(7->1->6->NULL)表示 617
(5->9->2->NULL)表示295
计算它们的和:结果是912,要求返回一个单链表表示和
分析:
低位数据相加可能产生进位,因此存在 调用者 ====> 被调用者 的数据传递
子问题必须返回链表的头节点指针,拼到当前和的后面, 因此存在 被调用者 ====> 调用者 的数据传递
Note: 要考虑两个链表长度不同等情况。
ListNode* SumOfListRecur(ListNode *lhs, ListNode *rhs, int flag)//flag表示进位
{
int n(0);
ListNode *sum(NULL), *end(NULL), *node(NULL);
if(lhs == NULL && rhs == NULL && flag == 0)//exit
return NULL;
assert(lhs != NULL || rhs != NULL || flag != 0);
n = flag;
if(lhs) n += lhs->val;
if(rhs) n += rhs->val;
flag = n/10;
n %= 10;
node = new ListNode(n);
sum = SumOfListRecur(lhs?lhs->next:NULL, rhs?rhs->next:NULL, flag);
assert(node != NULL);
node->next = sum;
return node;
}
浙公网安备 33010602011771号