链表
链表
一.实现链表的逆序
给定一个带头结点的单链表,请将其逆序.即如果单链表原来为head->1->2->3->4->5->6->7,则逆序后变为head->7->6->5->4->3->2->1
1.就地逆序
主要思路为:在遍历链表的时候,修改当前结点的指针域的指向,让其指向它的前驱结点.为此需要用一个指针变量来保存前驱结点的地址.此外,为了在调整当前结点指针域的指向后还能找到后续结点,还需要另外一个指针变量来保存后续结点的地址,在所有的结点都被保存好以后就可以直接完成指针的逆序了.除此之外,还需要特别注意对链表首尾结点的特殊处理
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
# 方法功能:对单链表进行逆序
# 输入参数:head 链表头结点
def Reverse(head):
if head==None or head.next==None:
return
pre=None # 前驱结点
cur=None # 当前结点
next=None # 后续结点
# 把链表首结点变为尾结点
cur=head.next
next=cur.next
cur.next=None
pre=cur
cur=next
# 使当前遍历到的结点cur指向其前驱结点
while cur.next!=None:
next=cur.next
cur.next=pre
pre=cur
cur=cur.next
cur=next
# 链表最后一个结点指向倒数第二个结点
cur.next=pre
# 链表的头结点指向原来链表的尾结点
head.next=cur
if __name__=="__main__":
i=1
head=LNode(i)
head.next=None
tmp=None
cur=head
while i<8:
tmp=LNode(i)
tmp.next=None
cur.next=tmp
cur=tmp
i+=1
print("逆序前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
print("\n逆序后:")
Reverse(head)
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
逆序前:
1 2 3 4 5 6 7
逆序后:
7 6 5 4 3 2 1
算法性能分析:这种方法只需要对链表进行一次遍历,因此时间复杂度为O(N),其中,N为链表的长度.但是需要常数个额外的变量来保存当前结点的前驱结点与后续结点,因此空间复杂度为O(1)
2.递归法
假定原链表为1->2->3->4->5->6->7,递归法的主要思路为:先逆序除第一个结点以外的子链表(将1->2->3->4->5->6->7变为1->7->6->5->4->3->2),依次类推
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
"""
方法功能:对不带头结点的单链表进行逆序
输入参数:firstRef 链表头结点
"""
def RecursiveReverse(head):
if head is None or head.next is None:
return head
else:
# 反转后面的结点
newhead=RecursiveReverse(head.next)
# 把当前遍历的结点加到后面结点逆序后链表的尾部
head.next.next=head
head.next=None
return newhead
"""
方法功能:对带头结点的单链表进行逆序
输入参数:head 链表头结点
"""
def Reverse(head):
if head is None:
return
firstNode=head.next
newhead=RecursiveReverse(firstNode)
head.next=newhead
return newhead
if __name__=="__main__":
i=1
head=LNode(i)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
tmp.next=None
cur.next=tmp
cur=tmp
i+=1
print("逆序前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
print("\n逆序后:")
Reverse(head)
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
逆序前:
1 2 3 4 5 6 7
逆序后:
7 6 5 4 3 2 1
算法性能分析:时间复杂度为O(N).递归法的主要优点是:思路比较直观,容易理解,而且也不需要保存前驱结点的地址.缺点是:算法实现的难度较大
3.插入法
插入法的主要思路:从链表的第二个结点开始,把遍历到的节点插入到头结点的后面,直到遍历结束
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def Reverse(head):
if head is None or head.next is None:
return
cur=None # 当前结点
next=None # 后续结点
cur=head.next.next
# 设置链表第一个结点为尾结点
head.next.next=None
# 把遍历到结点插入到头结点的后面
while cur is not None:
next=cur.next
cur.next=head.next
head.next=cur
cur=next
if __name__=="__main__":
i=1
head=LNode(i)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
tmp.next=None
cur.next=tmp
cur=tmp
i+=1
print("逆序前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
print("\n逆序后:")
Reverse(head)
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
算法性能分析:时间复杂度为O(N)
引申:
- 对不带头结点的单链表进行逆序
- 从尾到头输出链表
分析与解答:
- 就地逆序+顺序输出
- 逆序+顺序输出
- 递归输出
def ReversePrint(firstNode):
if firstNode is None:
return
ReversePrint(firstNode.next)
print(firstNode.data,end=" ")
二.从无序链表中移除重复项
1.顺序删除
主要思路为:通过双重循环直接在链表上进行删除操作.外层循环用一个指针从第一个结点开始遍历整个链表,然后内层循环用另外一个指针遍历其余结点,将与外层循环遍历到的指针所指结点的数据域相同的结点删除
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def removeDup(head):
if head==None or head.next==None:
return
outerCur=head.next # 用于外层循环,指向链表第一个结点
innerCur=None # 用于内层循环用来遍历outercur后面的结点
innerPre=None # innerCur的前驱结点
while outerCur!=None:
innerCur=outerCur.next
innerPre=outerCur
while innerCur!=None:
if outerCur.data==innerCur.data:
innerPre.next=innerCur.next
innerCur=innerCur.next
else:
innerPre=innerCur
innerCur=innerCur.next
outerCur=outerCur.next
if __name__=="__main__":
i=1
head=LNode(i)
head.next=None
tmp=None
cur=head
while i<7:
tmp=LNode(i)
if i%2==0:
tmp.data=i+1
elif i%3==0:
tmp.data=i-2
else:
tmp.data=i
tmp.next=None
cur.next=tmp
cur=tmp
i+=1
print("删除重复结点前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
removeDup(head)
print("\n删除重复结点后:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
删除重复结点前:
1 3 1 5 5 7
删除重复结点后:
1 3 5 7
**算法性能分析:**双重循环,其时间复杂度为O(N^2),空间复杂度为O(1)
2.递归法
主要思路为:对于结点cur,首先递归地删除以cur.next为首的子链表中重复的结点,接着从以cur.next为首的子链表中找出与cur有着相同数据域的结点并删除
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def removeDupRecursion(head):
if head.next is None:
return head
pointer=None
cur=head
head.next=removeDupRecursion(head.next)
pointer=head.next
while pointer is not None:
if head.data==pointer.data:
cur.next=pointer.next
pointer=cur.next
else:
pointer=pointer.next
cur=cur.next
return head
def removeDup(head):
if head is None:
return
head.next=removeDupRecursion(head.next)
if __name__=="__main__":
i=1
head=LNode(i)
head.next=None
tmp=None
cur=head
while i<7:
tmp=LNode(i)
if i%2==0:
tmp.data=i+1
elif i%3==0:
tmp.data=i-2
else:
tmp.data=i
tmp.next=None
cur.next=tmp
cur=tmp
i+=1
print("删除重复结点前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
removeDup(head)
print("\n删除重复结点后:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
删除重复结点前:
1 3 1 5 5 7
删除重复结点后:
1 3 5 7
算法性能分析:时间复杂度为O(N^2)
3.空间换时间
建立一个HashSet,HashSet中的内容为已经遍历过的结点内容,并将其初始化为空,从头开始遍历链表中的所有节点.如果结点内容已经在HashSet中,那么删除此结点,继续向后遍历,否则保留此结点,添加到HashSet,继续向后遍历
三.计算两个单链表所代表的数之和
1.整数相加法
分别求两个链表所代表的整数的值,然后把这两个整数进行相加,最后把它们的和用链表的形式表示出来.优点:计算简单.缺点:当链表所代表的数很大的时候(超出了long的表示范围),就无法使用这种方法了
2.链表相加法
对链表结点进行相加操作,把相加的和存储到新的链表中对应的结点中,同时还要记录结点相加后的进位
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def add(h1,h2):
if h1 is None or h1.next is None:
return h2
if h2 is None or h2.next is None:
return h1
c=0 # 用来记录进位
sums=0 # 用来记录两个结点相加的值
p1=h1.next
p2=h2.next
tmp=None # 用来指向新创建的存储相加和的结点
resultHead=LNode(1) # 相加后链表头结点
p=resultHead
while p1 is not None and p2 is not None:
sums=p1.data+p2.data+c
tmp=LNode(sums%10)
c=int(sums/10)
p.next=tmp
p=tmp
p1=p1.next
p2=p2.next
if p1 is None:
while p2 is not None:
sums=p2.data+c
tmp = LNode(sums%10)
c=int(sums/10)
p.next=tmp
p=tmp
p2=p2.next
if p2 is None:
while p1 is not None:
sums=p1.data+c
tmp = LNode(sums%10)
c=int(sums/10)
p.next=tmp
p=tmp
p1=p1.next
if c==1:
tmp=LNode(1)
p.next=tmp
return resultHead
if __name__=="__main__":
i=1
head1=LNode(i)
head2=LNode(i)
tmp=None
cur=head1
addResult=None
while i<7:
tmp=LNode(i+2)
cur.next=tmp
cur=tmp
i+=1
cur=head2
i=9
while i>4:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i-=1
print("Head1:")
cur=head1.next
while cur is not None:
print(cur.data,end=" ")
cur=cur.next
print("\nHead2:")
cur=head2.next
while cur is not None:
print(cur.data,end=" ")
cur=cur.next
addResult=add(head1,head2)
print("\n相加后:")
cur=addResult.next
while cur is not None:
print(cur.data,end=" ")
cur=cur.next
Head1:
3 4 5 6 7 8
Head2:
9 8 7 6 5
相加后:
2 3 3 3 3 9
四.对链表进行重新排序
给定链表L0->L1->L2…Ln-1->Ln,把链表重新排序为L0->Ln->L1->Ln-1->L2->Ln-2….要求:(1)在原来链表的基础上进行排序,即不能申请新的结点;(2)只能修改结点的next域,不能修改数据域
1.拆分
主要思路:
- 首先找到链表的中间结点
- 对链表的后半部分子链表进行逆序
- 把链表的前半部分子链表与逆序后的后半部分子链表进行合并,合并的思路为:分别从两个链表各取一个结点进行合并
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def FindMiddleNode(head):
if head is None or head.next is None:
return head
fast=head # 遍历链表的时候每次向前走两步
slow=head # 遍历链表的时候每次向前走一步
slowPre=head
# 当fast到链表尾时,slow恰好指向链表的中间结点
while fast is not None and fast.next is not None:
slowPre=slow
slow=slow.next
fast=fast.next.next
# 把链表断开成两个独立的子链表
slowPre.next=None
return slow
def Reverse(head):
if head is None or head.next==None:
return head
pre=head
cur=head.next
next=cur.next
pre.next=None
while cur is not None:
next=cur.next
cur.next=pre
pre=cur
cur=cur.next
cur=next
return pre
def Reorder(head):
if head is None or head.next==None:
return
cur1=head.next
mid=FindMiddleNode(head.next)
cur2=Reverse(mid)
tmp=None
while cur1.next is not None:
tmp=cur1.next
cur1.next=cur2
cur1=tmp
tmp=cur2.next
cur2.next=cur1
cur2=tmp
cur1.next=cur2
if __name__=="__main__":
i=1
head=LNode(i)
head.next=None
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
print("排序前:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
Reorder(head)
print("\n排序后:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
排序前:
1 2 3 4 5 6 7
排序后:
1 7 2 6 3 5 4
算法性能分析:时间复杂度为O(N),空间复杂度为O(1)
五.如何找出单链表中的倒数第k个元素
1.顺序遍历两遍法
首先遍历一遍单链表,求出整个单链表的长度n,然后求倒数第k个元素转换为求顺数第n-k个元素
2.快慢指针法
设置两个指针,让其中一个指针比另一个指针先前移k步,然后两个指针同时往前移动.循环直到先行的指针值为None时,另一个指针所指的位置就是所要找的位置
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def ConstructList():
i=1
head=LNode(1)
head.next=None
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
return head
def PrintList(head):
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
def FindLastK(head,k):
if head==None or head.next==None:
return head
slow=LNode(1)
fast=LNode(1)
slow=head.next
fast=head.next
i=0
while i<k and fast!=None:
fast=fast.next
i+=1
if i<k:
return None
while fast!=None:
slow=slow.next
fast=fast.next
return slow
if __name__=="__main__":
head=ConstructList()
result=None
print("链表:")
PrintList(head)
result=FindLastK(head,3)
if result!=None:
print("\n链表倒数第3个元素为:",result.data)
链表:
1 2 3 4 5 6 7
链表倒数第3个元素为: 5
算法性能分析:时间复杂度为O(N),空间复杂度为O(1)
六.如何将单链表向右旋转k个位置
主要思路:
- 首先找到链表倒数第k+1个结点slow和尾结点fast
- 把链表断开为两个子链表,其中后半部分子链表结点的个数为k
- 使原链表的尾结点指向链表的第一个结点
- 使链表的头结点指向原链表倒数第k个结点
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def RotateK(head,k):
if head==None or head.next==None:
return
slow,fast,tmp=LNode(1),LNode(1),None
slow,fast=head.next,head.next
i=0
while i<k and fast!=None:
fast=fast.next
i+=1
if i<k:
return
while fast.next!=None:
slow=slow.next
fast=fast.next
tmp=slow
slow=slow.next
tmp.next=None
fast.next=head.next
head.next=slow
def ConstructList():
i=1
head=LNode(1)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
return head
def PrintList(head):
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
if __name__=="__main__":
head=ConstructList()
print("旋转前:")
PrintList(head)
RotateK(head,3)
print("\n旋转后:")
PrintList(head)
旋转前:
1 2 3 4 5 6 7
旋转后:
5 6 7 1 2 3 4
算法性能分析:时间复杂度为O(N),空间复杂度为O(1)
七.如何检测一个较大的单链表是否有环
1.蛮力法
定义一个HashSet用来存放结点的引用
2.快慢指针遍历法
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def ConstructList():
i=1
head=LNode(1)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
cur.next=head.next.next.next
return head
def isLoop(head):
if head==None or head.next==None:
return None
slow=head.next
fast=head.next
while fast!=None and fast.next!=None:
slow=slow.next
fast=fast.next.next
if slow==fast:
return slow
return None
def findLoopNode(head,meetNode):
first=head.next
second=meetNode
while first!=second:
first=first.next
second=second.next
return first
if __name__=="__main__":
head=ConstructList()
meetNode=isLoop(head)
loopNode=None
if meetNode!=None:
print("有环")
loopNode=findLoopNode(head,meetNode)
print("环的入口点为:",loopNode.data)
else:
print("无环")
有环
环的入口点为: 3
算法性能分析:时间复杂度为O(N),空间复杂度为O(1)
八.如何把链表相邻元素翻转
把链表相邻元素翻转,例如给定链表为1->2->3->4->5->6->7,则翻转后的链表变为2->1->4->3->6->5->7
1.交换值法
交换相邻两个结点的数据域
2.就地逆序
主要思路:通过调整结点指针域的指向来直接调换相邻的两个结点.如果单链表恰好有偶数个结点,那么只需要将奇偶结点对调即可,如果链表有奇数个结点,那么只需要将除最后一个节点外的其它结点进行奇偶对调即可
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def reverse(head):
if head==None or head.next==None:
return
cur=head.next # 当前遍历结点
pre=head # 当前结点的前驱结点
next=None # 当前结点后续结点的后续结点
while cur!=None and cur.next!=None:
next=cur.next.next
pre.next=cur.next
cur.next.next=cur
cur.next=next
pre=cur
cur=next
def ConstructList():
i=1
head=LNode(1)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
return head
if __name__=="__main__":
head=ConstructList()
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
reverse(head)
print("\n逆序输出:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
1 2 3 4 5 6 7
逆序输出:
2 1 4 3 6 5 7
九.如何把链表以k个结点为一组进行翻转
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def ConstructList():
i=1
head=LNode(1)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
return head
def Reverse(head):
if head==None or head.next==None:
return head
pre=head
cur=head.next
next=cur.next
pre.next=None
while cur!=None:
next=cur.next
cur.next=pre
pre=cur
cur=cur.next
cur=next
return pre
def ReverseK(head,k):
if head==None or head.next==None or k<2:
return
i=1
pre=head
begin=head.next
end=None
pNext=None
while begin!=None:
end=begin
while i<k:
if end.next!=None:
end=end.next
else:
return
i+=1
pNext=end.next
end.next=None
pre.next=Reverse(begin)
begin.next=pNext
pre=begin
begin=pNext
i=1
if __name__=="__main__":
head=ConstructList()
cur=head.next
print("顺序输出:")
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
ReverseK(head,3)
print("\n逆序输出:")
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
顺序输出:
1 2 3 4 5 6 7
逆序输出:
3 2 1 6 5 4 7
十.如何合并两个有序链表
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def ConstructList(start):
i=start
head=LNode(1)
tmp=None
cur=head
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=2
return head
def PrintList(head):
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
def Merge(head1,head2):
if head1==None or head1.next==None:
return head2
if head2==None or head2.next==None:
return head1
cur1=head1.next
cur2=head2.next
head=None
cur=None
if cur1.data>cur2.data:
head=head2
cur=cur2
cur2=cur2.next
else:
head=head1
cur=cur1
cur1=cur1.next
while cur1!=None and cur2!=None:
if cur1.data<cur2.data:
cur.next=cur1
cur=cur1
cur1=cur1.next
else:
cur.next=cur2
cur=cur2
cur2=cur2.next
if cur1!=None:
cur.next=cur1
if cur2!=None:
cur.next=cur2
return head
if __name__=="__main__":
head1=ConstructList(1)
head2=ConstructList(2)
print("Head1:")
PrintList(head1)
print("\nHead2:")
PrintList(head2)
print("\n合并后的链表:")
head=Merge(head1,head2)
PrintList(head)
Head1:
1 3 5 7
Head2:
2 4 6
合并后的链表:
1 2 3 4 5 6 7
算法性能分析:时间复杂度为O(N),空间复杂度为O(1)
十一.如何在只给定单链表中某个结点的指针的情况下删除该结点
分两种情况来分析:
- 如果这个结点是链表的最后一个结点,那么无法删除这个结点
- 如果这个结点不是链表的最后一个结点,可以通过把其后续结点的数据复制到当前结点中,然后删除后续结点的方法来实现
class LNode(object):
def __init__(self,data):
self.data=data
self.next=None
def ConstructList():
i=1
head=LNode(1)
tmp=None
cur=head
p=None
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
if i==5:
p=tmp
i+=1
return head,p
def PrintList(head):
cur=head.next
while cur!=None:
print(cur.data,end=" ")
cur=cur.next
def RemoveNode(p):
if p==None or p.next==None:
return False
p.data=p.next.data
tmp=p.next
p.next=tmp.next
return True
if __name__=="__main__":
head,p=ConstructList()
print("删除结点"+str(p.data)+"前链表")
PrintList(head)
result=RemoveNode(p)
if result:
print("\n删除该结点后链表")
PrintList(head)
删除结点5前链表
1 2 3 4 5 6 7
删除该结点后链表
1 2 3 4 6 7
十二.如何判断两个单链表(无环)是否交叉
1.Hash法
2.首尾相接法
将两个链表首尾相连(例如把链表head1尾结点链接到head2的头指针),然后检测这个链表是否存在环,如果存在,则两个链表相交,二环入口结点即为相交的结点
3.尾结点法
如果两个链表相交,那么两个链表从相交点到链表结束都是相同的结点,必然是Y字形.即判断两个链表的最后一个结点是不是相同即可.分别遍历记下两个链表的长度n1,n2,在遍历一次,长链表结点先出发前进|n1-n2|步,之后两个链表同时前进,每次一步,相遇的第一点即为两个链表相交的第一个点
class LNode:
def __init__(self,data):
self.data=data
self.next=None
def IsIntersect(head1,head2):
if head1==None or head1.next==None or head2==None or head2.next==None or head1==head2:
return None
temp1=head1.next
temp2=head2.next
n1,n2=0,0
while temp1.next!=None:
temp1=temp1.next
n1+=1
while temp2.next!=None:
temp2=temp2.next
n2+=1
if temp1==temp2:
if n1>n2:
while n1-n2:
head1=head1.next
n1-=1
if n1<n2:
while n2-n1>0:
head2=head2.next
n2-=1
while head1!=head2:
head1=head1.next
head2=head2.next
return head1
else:
return None
if __name__=="__main__":
i=1
head1=LNode(1)
head2=LNode(1)
tmp=None
cur=head1
p=None
while i<8:
tmp=LNode(i)
cur.next=tmp
cur=tmp
if i==5:
p=tmp
i+=1
cur=head2
i=1
while i<5:
tmp=LNode(i)
cur.next=tmp
cur=tmp
i+=1
cur.next=p
interNode=IsIntersect(head1,head2)
if interNode==None:
print("两个链表不相交")
else:
print("两个链表相交 "+str(interNode.data))
两个链表相交 5
算法性能分析:时间复杂度为O(n1+n2),空间复杂度为O(1)
引申:如果单链表有环,如何判断两个链表是否相交
分析与解答:
- 如果一个单链表有环,另外一个没环,那么它们肯定不相交
- 如果两个单链表都有环并且相交,那么这两个链表一定共享这个环.判断两个有环的链表是否相交的方法为:首先采用第7题介绍的找到链表head1中环的入口点p1,然后遍历链表head2,判断链表中是否包含结点p1,如果包含则相交,否则不相交;找相交点的方法为:把结点p1看作两个链表的尾结点,这样就可以把问题转换为求两个无环链表相交点的问题
十三.展开链表列表
from IPython.display import Image
Image("./data/test2.png",width=500)
实现一个函数flatten(),该函数将链表扁平化成单个链表,扁平化的链表也应该被排序.输出链表为:3->6->8->11->15->21->22->30->31->39->40->45->50.主要思路使用归并排序中的合并排序,使用归并的方法用这些链表来逐个归并
class LNode:
def __init__(self,data):
self.data=data
self.right=None
self.down=None
class MergeList:
def __init__(self):
self.head=None
# 用来合并两个有序的链表
def merge(self,a,b):
if a==None:
return b
if b==None:
return a
# 把两个链表头中较小的结点赋值给result
if a.data<b.data:
result=a
result.down=self.merge(a.down,b)
else:
result=b
result.down=self.merge(a,b.down)
return result
# 链表扁平化处理
def flatten(self,root):
if root==None or root.right==None:
return root
# 递归处理root.right链表
root.right=self.flatten(root.right)
# 把root结点对应的链表与右边的链表合并
root=self.merge(root,root.right)
return root
# 将data插入链表头
def insert(self,head_ref,data):
new_node=LNode(data)
new_node.down=head_ref
head_ref=new_node
# 返回新的表头结点
return head_ref
def printList(self):
temp=self.head
while temp!=None:
print(temp.data,end=" ")
temp=temp.down
if __name__=="__main__":
L=MergeList()
L.head=L.insert(L.head,31)
L.head=L.insert(L.head,8)
L.head=L.insert(L.head,6)
L.head=L.insert(L.head,3)
L.head.right=L.insert(L.head.right,21)
L.head.right=L.insert(L.head.right,11)
L.head.right.right=L.insert(L.head.right.right,50)
L.head.right.right=L.insert(L.head.right.right,22)
L.head.right.right=L.insert(L.head.right.right,15)
L.head.right.right.right=L.insert(L.head.right.right.right,55)
L.head.right.right.right=L.insert(L.head.right.right.right,40)
L.head.right.right.right=L.insert(L.head.right.right.right,39)
L.head.right.right.right=L.insert(L.head.right.right.right,30)
L.head=L.flatten(L.head)
L.printList()
3 6 8 11 15 21 22 30 31 39 40 50 55