此处明确了实现的方法,另外非递归(迭代)的方法也可行。
首先我们需要知道一些基础知识--即递归的相关概念。递归(Recursion)即函数自己调用自己,若问题可以使用递归来解决,则必须满足以下三个条件:
说明:递归可以解决的方法,非递归一定也可以.
2.可以应用这个转化过程使问题得到解决。
说明:使用其他方法(非递归的)一定存在同样可以解决问题的方法,但效率可能不如递归
3.必须要有一个明确的结束递归的条件。
说明:该条件是我们一开始就知道或者说设置好的,作为过程的出口。
递归的核心:逐级调用,逐级返回
说明:
1.当函数自己调用自己时,系统将自动把函数当前的变量和形参暂时保留起来,在新一轮的调用过程中,系统为新调用的函数所用到的变量和形参开辟另外的存储单元(即内存空间),每次调用函数所使用的变量在不同的内存空间中。
2.递归调用的层次越多,同名变量(因为就是函数自身)占用的存储单元也就越多。每次函数的调用,系统都会为该函数的变量开辟新的内存空间。
3.当本次调用的函数运行结束时,系统将释放本次调用时所占用的内存空间。程序的流程返回到上一层的调用点,同时期的当初进入该层时,函数的变量和形参所占用的内存空间的数据(这点很重要,它使我们的结果在不断的变化中,直到遇到出口)
下面是关于链表反转实现的思路
与迭代不同的是,递归是从后向前,即从尾节点向头节点逐个翻转来实现效果的。
首先我们假定创建了一个共有5个节点的链表,像下边这样:
之后我们建立一个新的变量NewH,并同时移动H直到它们指向尾节点,此时NewH作为新的头节点,其指向固定在此位置
然后H指针逐层返回的时候做下图的处理,将H的指向的地址赋值给H->next->next指针,并一定注意要让H->next=NULL
说明:此处为操作的核心,实现了断链和反转其指向的功能。由递归的相关概念我们可以知道,逐级返回的一开始,head就指向前一个节点了(即'4'这个节点),而head->next->next与head的基准是不一样的!前一个在此时指的是'5'这个节点,因此其next的next,即null的next,本来是指向未开辟的(无法输出)内存,但此时我们将它改为指向前一个节点,实现了反转的效果,并在此操作后将'4'这个节点断开(即指向NULL)
继续上述操作:
直到返回到头:
部分代码如下:
ListNode* reverse(ListNode* H) {
//包括特殊情况
if (H == NULL || H->next == NULL)
return H;
ListNode *newH = reverse(H->next);//注意,此处的操作是一直循环到链表末尾
H->next->next = H;//反转每个节点的指向
H->next = NULL;
return newH;
}
参考资料:
1.https://blog.csdn.net/fx677588/article/details/72357389
2.http://www.jb51.net/article/39918.htm