python单向链表逆序_python算法-003单链表逆序插入法

被压抑的情感并不会消失,累积到一定程度后,反而以更丑恶的方式爆发出来,有些精神病就是这样造成的。若是一味压抑,不能把愤懑的情绪加以升华,自我评价将日趋低落。——《高效能人士的七个习惯》

这段话告诉我们,心里有事一定要说出来,找人倾诉,或者写出来。或者是bug出多了,会被气炸,甚至砸了这破电脑……我们还是努力学习吧!

题目:给定一个带头节点的单链表:head->1->2->3->4->5->6->7->8;使其成为:head->8->7->6->5->4->3->2->1。

今天的题目还是将单链表逆序,前面已经写过两种方法了,一篇就地逆序法,一篇递归法。就地逆序法是将遍历到的节点逆序,需要将整个链表遍历一遍,时间复杂度为O(n),需要常数个额外变量来保存当前节点的前驱节点和后继节点,因此空间复杂度为O(1)。

递归法在性能上要比就地逆序法差一点。其优点是思路直观,很容易理解;但是其缺点就是实现起来要难一点,还有一点就是Python支持的递归深度为默认是 1000,在昨天的代码中,我将链表的长度加到998就是极限了,会报出下面图中的错误。

f5da6bc90f2b?from=timeline&isappinstalled=0

递归溢出

经过查找资料,这是python专门设置的一种机制用来防止无限递归造成Python溢出崩溃,默认深度是可以改的:

import sys

sys.setrecursionlimit(1500) # 这是将递归深度改为1500

好的,今天的方法是插入法。

插入法的主要思路是,从链表的第二个节点开始遍历,将遍历到的当前节点插入到头节点的后面,直到遍历完所有节点。即原链表为head->1->2->3->4->5->6->7->8,从2开始遍历,将其插入1前面,也就是头节点后面:head->2->1->3->4->5->6->7->8,然后遍历到3,同理将其插入到头节点后面。当所有节点都插入头节点head后面,就可以实现链表的逆序。

我们要逆序链表当然得现有一个链表,链表的构造方法我在昨天文章写了,看不懂可以看看—— python算法-002单链表逆序递归法 ,下面代码实现:

#先构造节点对象

class LNode:

"""

定义链表对象

"""

def __init__(self, x):

self.data = x

self.next = None

#构造链表函数

def creatLink(x):

i = 1

head = LNode(None)

tmp = None

cur = head

while i <= x:

tmp = LNode(i)

cur.next = tmp

cur = tmp

i += 1

链表有了,接下来就是实现算法:

def Reverse(head):

'''

带头节点

输入: 链表

输出: 逆序后的链表

'''

#先判断链表是否为空或这只有一个元素,是则返回

if head is None or head.next is None:

return head

cur = None # 用来遍历链表

next = None # 用来指向当前节点的后继节点

cur = head.next.next # 从链表的第二个节点开始遍历

head.next.next= None # 断开第一个节点与第二个节点。

# 注意这里是重点!一定要断开,因为不断开的话,在下一步中

# 第二个节点的next域为第一个节点,但是第一个节点的next域为第二个节

# 点,这就成了一个最小的环,那么后面的程序就进入了死循环

while cur is not None:

next=cur.next # next用来保存cur的后继节点,不然会丢失后面的节点

cur.next=head.next # 将当前遍历的节点插入到头节点之后

head.next = cur #这里的两步实现的“插入”,细细体会

cur = next # 遍历下一个节点

return head

算法到这里就写完了,下面我们来试一试这个算法:

if __name__=='__main__':

# 构造链表

head=creatLink(8)

#打印逆序前的链表

print("BeforeReverse:")

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

print("\nAfterReverse:")

#调用逆序函数

head=Reverse(head)

#打印逆序后的链表

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

这是运行成果:

f5da6bc90f2b?from=timeline&isappinstalled=0

程序运行结果

给一下全部的代码:

#先构造节点对象

class LNode:

"""

定义链表对象

"""

def __init__(self, x):

self.data = x

self.next = None

#构造链表函数

def creatLink(x):

i = 1

head = LNode(None)

tmp = None

cur = head

while i <= x:

tmp = LNode(i)

cur.next = tmp

cur = tmp

i += 1

def Reverse(head):

'''

带头节点

输入: 链表

输出: 逆序后的链表

'''

#先判断链表是否为空或这只有一个元素,是则返回

if head is None or head.next is None:

return head

cur = None # 用来遍历链表

next = None # 用来指向当前节点的后继节点

cur = head.next.next # 从链表的第二个节点开始遍历

head.next.next= None # 断开第一个节点与第二个节点。

# 注意这里是重点!一定要断开,因为不断开的话,在下一步中

# 第二个节点的next域为第一个节点,但是第一个节点的next域为第二个节

# 点,这就成了一个最小的环,那么后面的程序就进入了死循环

while cur is not None:

next=cur.next # next用来保存cur的后继节点,不然会丢失后面的节点

cur.next=head.next # 将当前遍历的节点插入到头节点之后

head.next = cur #这里的两步实现的“插入”,细细体会

cur = next # 遍历下一个节点

return head

if __name__=='__main__':

# 构造链表

head=creatLink(8)

#打印逆序前的链表

print("BeforeReverse:")

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

print("\nAfterReverse:")

#调用逆序函数

head=Reverse(head)

#打印逆序后的链表

cur = head.next

while cur != None:

print(cur.data)

cur = cur.next

好了,今天的算法是对有头节点的链表写的,不带头节点的你会吗?欢迎来讨论,在我的github上也有代码,你可以对照一下,亦可以将你的代码发我给我、私信我,也可以关注我自己的公众号:DKider 来联系我。

我们一起加油吧!

力学如力耕,勤惰尔自知。但使书种多,会有岁稔时。——宋 刘过《书院》

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值