算法中,最简单但是又让人理解起来比较困难的算法就是递归了。
今天IT圈圈给你分享下怎么理解它:
先听我讲个老故事
一位优秀的商人杰克,有一天告诉他的儿子...
杰克:我已经决定好了一个女孩子,我要你娶她。
儿子:我自己要娶的新娘,我自己会决定。
杰克:但我说的这女孩,可是比尔盖茨的女儿喔!
儿子:哇!那这样的话...
在一个聚会中,杰克走向比尔盖茨...
杰克:我来帮你女儿介绍个好丈夫。
比尔:我女儿还没想嫁人呢!
杰克:但我说的这年轻人,可是世界银行的副总裁喔!
比尔:哇!那这样的话...
接著,杰克去见世界银行的总裁。
杰克:我想介绍一位年轻人来当贵行的副总裁。
总裁:我们已经有很多位副总裁,够多了!
杰克:但我说的这年轻人,可是比尔盖茨的女婿喔!
总裁:哇!那这样的话...
悟出道理
这个故事告诉我们一个道理,我可以先假设一个事情,再这个假设基础上,我们做接下来的事情。
用到算法上,我们先假设后面的递归调用已经帮我们做好了,我们写接下来的的事情。
这个假设就是递归的精髓。
而递归其实真的是一个成功的说客。
反转一个链表
现在我们用递归实现:反转一个单向链表。
reverse_ll(struct node ** hasHref)
{
struct node * first,last;
if(hasHerf ==null) return -1;
first = * hasHref;//伪装成第一个
rest = first->next;
if(rest == null) return ;//后面没有了,退出
reverse_ll(&rest);//说客在这里,从第二个元素开始,“假装(递归)”这个元素的右边部分已经被反转,然后在“假装”的基础上,交换左边和右边
first->next->next =first;
firest->next = null;
|
以此类推,每个函数调用都要假装,直到假装不下去了,还剩最后一个的时候返回。
示意图
-
刚开是链表是这样的
-
然后从第二个开始"假装"如下:234“已经”被反转,然后交换
-
现在列表“实际”如下
-
然后2伪装成第一个,重复过程:从3开始"假装"如下:34“已经”被反转完成,然后交换
-
然后3伪装成第一个,4开始伪装右边已好,虽然他右边没有了
-
然后4伪装成第一个,发现没有rest了,退出
总结
这里注意,函数的执行顺序和我们的图解正好是反的,所以我们可以把伪装成第一个的下一个设为null,firest->next = null,为后面函数返回后指向后面的腾出空间。
喜欢IT圈圈的文章,请长按关注下吧