链表的反转(递归实现)

此处明确了实现的方法,另外非递归(迭代)的方法也可行。

首先我们需要知道一些基础知识--即递归的相关概念。递归(Recursion)即函数自己调用自己,若问题可以使用递归来解决,则必须满足以下三个条件:

1.可以要把解决的一个问题转化为一个新的问题,这个新问题的解决思路与原来相同,只是在有规律的变化(例如递增递减).

说明:递归可以解决的方法,非递归一定也可以.

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

  
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章