关于链表逆置的问题
最近在刷Leetcode上面的题目,其中有一道题是这样的,给你一个链表,每个节点存储一个数字,将每个节点逆序输出的数组中。链表的长度为0<=长度<=10000。例如,链表的结点分别存储为1,3,2,则输出到的结果应该为2,3,1。我的解题思路是这样的:
1、将链表逆置。
2、将链表中的数字存储进入数组中。
所以这道题的难点就是如何将链表逆置(第二步我想基本都会吧)。
首先我总结解决数据结构的题目要有两个部分。第一就是解题思路,换句话说,无论是在头脑中想出来的也好,还是在纸上画出来也好,必须要对思路有一个清晰的构建。第二就是范围,比如拿这道题来说,如果链表是空的该怎么办?这就是我们要思考的两个问题。
好,我们接下来就分析一下解题思路。首先,解决链式存储结构必须要借用指针,那么这道题我们应该使用几个指针呢?我的答案是三个。为什么呢?首先我们如果要逆置链表,那么逆置的两个结点肯定是各需要一个指针了,但是,不要忘记,在逆置之后,与之前连接的结点我们就找不到了,所以我们还需要一个指针来指向原来找不到的那个结点。如图所示。
如图,如果我们想将结点2指向结点3的结点改为指向结点1,那么我们改变后结点三就找不到了,因此我们要留一个指针指向结点3。
好了,我们搞清楚了这个问题,那么我们的边界问题就搞清楚了,如果我们有两个结点,一个结点,0个结点该怎么办呢?
所以,我们的整体架构图应该是这样的。
1、如果是空链表 解决方案
2、如果链表中只有一个结点 解决方案
3、如果链表中只有两个结点 解决方案
4、如果是三个以上结点 解决方案
如前文所述,前三个都是极端情况,请各位自行处理(因为很简单),我们这里只说最后一种。
好了,接下来我们说一下逆置的具体解决方案。我个人觉得可以分成三个部分。其中第一部分就是准备工作,包括定义指针,确定指针的位置。第二部分就是具体的移动。最后一部分就是处理一些善后工作,比如头指针的移动位置等等。
第一部分:第一部分的重点在于指针位置的确定。其实我觉得只要头结点有一个指针,剩下的两个指针放到哪个结点都可以。(当然,因为在第二步骤中,指针位置不同,会让你的代码稍有不同)。我这里的话为了方便,头节点放一个指针,接下来的结点放了两个指针。
第二部分:这一部分也是所有部分中最关键的部分。这一部分又可以细化成三个部分,首先,第一就是移动指针,就是要将三个指针分开,按照上图所示各放置一个结点,第二部分就是实现单个结点逆置,拿上图来说将结点2指向结点3的指针指向结点1。第三部分就是所有指针以第一步骤为参照物,全部向前移动一位。
这里要说一点,就是范围的问题,因为在移动的过程中必须使用使用循环语句,所以范围很重要。这里我们绝不能使用p1->next = NULL,因为我们逆置了以后p1->next永远不可能为NULL,所以我们应该使用的是p2=NULL。
第三部分:这一部分就是收尾工作,将原来的头指针的下一结点指向空,并将原来的头指针指向新的第一个结点。
好的,我们总结一下整个的算法流程:
1、如果是空链表 解决方案
2、如果链表中只有一个结点 解决方案
3、如果链表中只有两个结点 解决方案
4、如果链表中有三个以上的结点
4.1 定义指针并指向相应的结点
4.2 实现链表逆置
4.2.1 移动指针,使其分开
4.2.2 移动指针,实现单个结点的逆置
4.2.3 所有指针向前移动一位
4.3 将头指针移动到新的最新结点之上
好了,链表逆置的思路就差不多是这些了。