欢迎关注公众号:
题目:从尾到头打印链表arrayList
题目描述:输入一个链表,按链表值从尾到头的顺序返回一个ArrayList。
思路分析:
(1)链表简介:链表是这样一种数据结构,它是线性表,表示逻辑有序,即即数据之间的顺序关系是由某种逻辑关系(如指针)来决定的,其结构如下图所示,每一个节点包括有当前节点的数值和下一个节点的地址。(后面我们在数据结构和算法中详细介绍链表)
(2)逻辑分析:在上面的描述中我们知道链表的基本结构,那么,如何实现链表的反转呢?目前有两种思路
<1>链表是一种链式存储的数据结构,我们可以遍历链表,将链表中的数值存储到list中,然后倒序打印list。如下图所示,倒序输出list。
<2>链表上的节点存储当前位置的值和下一个节点的位置,如下图所示。
对于每一个节点,我们将next的位置指向前一个节点,这样相当于将链表反转,如下图所示:
反转前:
反转后:
反转的过程为:
反转的过程为:
对节点v做反转时,如反转前的图所示,u的next域指向v,v的next域指向w。现在要做的是将v的next域指向u。从图中我们可以看出,当把v的next指针指向u的同时,w节点及其后面的节点无法访问,为了避免“断链”,我们必须在指针更改指向之前,保存修改结点的下一结点。同时我们也必须存储上一个结点,因为next域即将修改指向该结点。因此定义三个指针,分别指向当前遍历的结点(head),前一个结点(pre)和后一个结点(next)。
具体代码实现过程如下。
【第一种思路】
# -*- coding:utf-8 -*-
class ListNode:
#在初始化方法中定义链表的节点,
def __init__(self, x):
self.val = x
self.next = None
class Solution:
# 返回从尾部到头部的列表值序列,例如[1,2,3]
def printListFromTailToHead(self, listNode):
# write code here
# 定义一个空数组,用于存储链表中的数值
l=[]
# 遍历链表,
while listNode:
# 将链表中的当前节点的数值存储到list中,
l.append(listNode.val)
# 下个节点的值赋值给当前节点
listNode=listNode.next
return l[::-1]
if __name__=='__main__':
#首先我们定义一个链表节点:1,2,3,4,5
A1 = ListNode(1)
A2 = ListNode(2)
A3 = ListNode(3)
A4 = ListNode(4)
A5 = ListNode(5)
#然后创建链表, 1-->2-->3-->4-->5
A1.next=A2
A2.next=A3
A3.next=A4
A4.next=A5
print("打印反转前链表")
print ( A1.val , A2.val,A3.val,A4.val,A5.val)
solution=Solution()
#调用方法,返回数组
ans=solution.printListFromTailToHead(A1)
print("打印反转后链表")
print(ans)
在上述代码中,从前向后遍历链表,并将链表中的数依次赋值给list,然后倒序输出list。
上述代码运行结果如下。
【第二种思路】
class Node ( object ) :
def __init__ ( self , elem , next_ = None ) :
self.elem = elem
self.next = next_
def reverseList ( head ) :
if head == None or head.next == None : # 若链表为空或者仅一个数就直接返回
return head
pre = None
next = None
while (head != None) :
# 用临时变量 pre 和 next 实现 头节点的值和指向下一个节点的位置的变换
# 即pre 和 next作为临时节点,head及head.next作为要变换的节点,
next = head.next # 1
head.next = pre # 2
pre = head # 3
head = next # 4
return pre
if __name__ == '__main__' :
l1 = Node ( 1 ) # 建立链表3->2->1->9->None
l1.next = Node ( 2 )
l1.next.next = Node ( 3 )
l1.next.next.next = Node ( 4 )
l1.next.next.next.next = Node ( 5 )
print("反转前:")
print ( l1.elem , l1.next.elem , l1.next.next.elem , l1.next.next.next.elem,l1.next.next.next.next.elem )
l = reverseList ( l1 )
print("反转后:")
print ( l.elem , l.next.elem , l.next.next.elem , l.next.next.next.elem, l.next.next.next.next.elem)
运行结果为:
上述代码中,首先定义一个链表 ,如下图所示:
反转之后链表如下图所示。
那么,当我们调用函数时,已知链表不为空或只有一个节点,pre=None,next=None,当head不为空时,
在第一次循环时,对于链表的第一个节点 1 及1.next
next = head.next
第一步:next = head.next
将 head.next 赋值给 next 变量,即next 指向了节点2,先将节点2 保存起来。
head.next = pre
第二步:head.next = pre (初始pre==None)
将 pre 变量赋值给 head.next,即 此时节点1 指向了 None
pre = head
第三步:pre = head
将 head 赋值给了 pre,即 pre 指向节点1,将节点1 设为“上一个节点”
head = next
第四步:head = next
将 next 赋值给 head,即 head 指向了节点2,此时节点2 设为“头节点”
第一遍循环执行完毕,
反转前:
反转后:
进入第二遍循环,
next = head.next # 1
head.next = pre # 2
pre = head # 3
head = next # 4
第一步:next = head.next
将 head.next 赋值给 next 变量,即 next 指向了节点3,先将节点3 保存起来。
第二步:head.next = pre (此时的pre已经不为None)
将 pre 赋值给 head.next,pre 在上一次循环的时候指向了节点1,那么这一步的意义就是节点2 指向了 节点1,完成1和2节点的反转。
第三步:pre = head
将 head 赋值给了 pre,即 pre 指向节点2,将节点2 设为“上一个节点”
第四步:head = next
将 next 赋值给 head,即 head 指向了节点3。此时节点3 设为“头节点”
第二次循环完毕,以此类推,执行后面的循环,最后结果如下图所示:
在上述遍历的过程中,
(1)pre指向反转后链表的第一个节点,next指向反转前链表的第一个节点,head指向当前节点,反转的过程如下图所示。
(2)当前节点的下一个节点一定要保存,如不保存,下一次循环时无法找到反转前链表的节点,如当前节点为2,则先将节点3保存起来
(3)实现反转的关键点在:head.next = pre