遞歸就是函數調用自己,來解決子問題,經過子問題的解構造本問題的解。node
遞歸能夠用於簡化程序,讓程序結構明瞭。。函數
調用者與被調用者之間有如下的四種數據傳遞關係:spa
1>沒有任何數據傳遞指針
e.g. 打印鏈表code
void PrintList(ListNode const *list) { if(list == NULL) return; //exit cout << list->val << " "; PrintList(list->next); }
2> 調用者 <= === 被調用者blog
這是咱們一般習慣的數據傳遞(經過解決子問題,來解決本問題)遞歸
e.g. 計算階乘ip
int f(int n) { if(n == 0 || n == 1) return 1; return n * f(n-1); }
3> 調用者 = ===> 被調用者it
其實咱們從小學的數的加法運算就能夠認爲是這種狀況。class
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; }