python中的list就是链表吗_数据结构之链表(Linked list)

1, 无序链表(Unordered linked list)

链表是有若干个数据节点依次链接成的数据结构,如下图所示,每一个数据节点包括包括数据和一个指向下一节点的指针。(python中的list就是由链表来实现的)

无序链表操作:

Llist = UnorderedList() #创建无序链表

add(item) #向链表中加入item(首部加入)

remove(item) #从链表中移除item

search(item) #从链表中搜索item

pop() #从链表末尾移除节点

append() #从链表末尾加入节点

pop(pos) #从链表指定位置移除节点

insert(pos, item) #从链表指定位置加入节点

index(item) #返回item在链表中的位置

size() #返回链表大小

isEmpty() #返回链表是否为空

python实现无序链表

定义了Node类和UnorderedList类,代码如下:

#coding:utf-8

classNode(object):def __init__(self,data):

self.data=data

self.next=NonedefgetData(self):returnself.datadefgetNext(self):returnself.nextdefsetData(self,newData):

self.data=newDatadefsetNext(self,newNext):

self.next=newNextclassUnorderedList(object):def __init__(self):

self.head=Nonedefadd(self,item):

temp=Node(item)

temp.setNext(self.head)

self.head=tempdefremove(self,item): #未考虑item不存在链表中的情况,考虑时参见下面有序列表中remove方法

previous=None

current=self.head

found=Falseifcurrent:while notfound:if current.getData()==item:

found=Trueelse:

previous=current

current=current.getNext()if previous==None:

self.head=current.getNext()else:

previous.setNext(current.getNext())returnfounddefsearch(self,item):

current=self.head

found=Falsewhile current!=None and (notfound):if current.getData()==item:

found=Truereturncurrentelse:

current=current.getNext()returnfounddefpop(self):

previous=None

current=self.headifcurrent:while current.getNext()!=None:

previous=current

current=current.getNext()if previous==None:

self.head=Noneelse:

previous.setNext(None)else:raise IndexError("pop from empty unorderedList")returncurrent.getData()defappend(self,item):

temp=Node(item)

current=self.head

previous=Nonewhile current!=None:

previous=current

current=current.getNext()if previous==None:

self.head=tempelse:

previous.setNext(temp)defindex(self,item):

count=0

current=self.headwhile current and (current.getData()!=item):

count= count+1current=current.getNext()if count and (count

count=0

current=self.headwhile current!=None:

count+= 1current=current.getNext()returncountdefisEmpty(self):return self.head==None

u=UnorderedList()

u.append(3)

u.append(2)

u.append(6)#print u.index(6), u.index(7)

printu.size(),u.pop()printu.size(),u.pop()print u.size(),u.pop()

链表排序

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))

利用归并排序对链表排序

def sort_list(head):if head==None or head.next==None:returnhead

left=head

mid=get_mid(head)

right=mid.next

mid.next=Nonereturnmerge(sort_list(left),sort_list(right))

def merge(left, right):

node= ListNode(0)

temp=nodewhileleft and right:if left.data>=right.data:

temp.next=right

right=right.nextelse:

temp.next=left

left=left.next

temp=temp.nextifleft:

temp.next=leftifright:

temp.next=rightreturnnode.next

def get_mid(node):if node==None:returnnode

slow=node

fast=nodewhilefast.next and fast.next.next:

slow=slow.next

fast=fast.next.nextreturnslow

l1.traverse()

sort_list(l1)

l1.traverse()

print("*"*20)

l2.traverse()

sort_list(l2)

l2.traverse()

归并排序

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))

#利用堆来排序

def sort_list2(head):if head==None:returnhead

temp=head

import heapq

hq=[]whiletemp:

heapq.heappush(hq,temp.data)

temp=temp.next

head=ListNode(heapq.heappop(hq))

prev=headwhilehq:

current=ListNode(heapq.heappop(hq))

prev.next=current

prev=prev.next

l1.traverse()

sort_list2(l1)

l1.traverse()

print("*"*20)

l2.traverse()

sort_list2(l2)

l2.traverse()

堆排序

链表倒转

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(5,ListNode(9,ListNode(7,ListNode(10,ListNode(12)))))

def reverse(head):

prev=head

cur=head.next

prev.next=Nonewhilecur:

temp=cur.next

cur.next=prev

prev=cur

cur=tempreturnprev

l1.traverse()

r=reverse(l1)

print("="*30)

r.traverse()

单链表倒转

#链表翻转。给出一个链表和一个数k,比如,链表为1→2→3→4→5→6,k=2,则翻转后2→1→6→5→4→3,若k=3,翻转后3→2→1→6→5→4,若k=4,翻转后4→3→2→1→6→5,用程序实现。class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

def reverse(head):

prev=head

cur=head.next

prev.next=Nonewhilecur:

temp=cur.next

cur.next=prev

prev=cur

cur=tempreturnprev,head

def reverse_linkedlist(head,k):

temp=headfor i in range(k-1):

temp=temp.nextif temp==None:returnNone

mid=temp.next

temp.next=None

head1,end1=reverse(head)

head2,end2=reverse(mid)

end1.next=head2returnhead1

l2= reverse_linkedlist(l1,3)

l2.traverse()

复杂链表倒转

判断链表是否有环,并返回环入口点,计算环长度

(1)题目描述:输入一个单向链表,判断链表是否有环?

分析:通过两个指针,分别从链表的头节点出发,一个每次向后移动一步,另一个移动两步,两个指针移动速度不一样,如果存在环,那么两个指针一定会在环里相遇。

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(31,ListNode(26,ListNode(18,ListNode(32))))

#在链表中构造环路

def cycle_list(l1):

first=l1

temp=firstfor i in range(3): #向后移动三次,即将20作为入环节点

temp=temp.nextwhilefirst.next:

first=first.next

first.next=tempreturnl1

l3=cycle_list(l1)

#l3.traverse()

#检查是否存在环路

def check_cycle(head):

slow= fast =headwhile fast!=None and fast.next!=None:

fast=fast.next.next

slow=slow.nextif slow isfast:returnTruereturnFalse

print(check_cycle(l2)) #False

print(check_cycle(l3)) #True

判断是否有环

(2)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,如何找到环的入口点?

解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,让p2回到链表的头部,重新走,每次步长不是走2了,而是走1,那么当 p1 和 p2 再次相遇的时候,就是环路的入口了。

为什么?:假定起点到环入口点的距离为 a,p1 和 p2 的相交点M与环入口点的距离为b,环路的周长为L,当 p1 和 p2 第一次相遇的时候,假定 p1 走了 n 步。那么有:

p1走的路径: a+b = n;

p2走的路径: a+b+k*L = 2*n; p2 比 p1 多走了k圈环路,总路程是p1的2倍

根据上述公式可以得到 k*L=a+b=n显然,如果从相遇点M开始,p1 再走 n 步的话,还可以再回到相遇点,同时p2从头开始走的话,经过n步,也会达到相遇点M。显然在这个步骤当中 p1 和 p2 只有前 a 步走的路径不同,所以当 p1 和 p2 再次重合的时候,必然是在链表的环路入口点上。因为p1和p2点同时到达相遇点M,若都往后倒退b步则为环入口点,则第一次重合点必然是环路入口点。

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(31,ListNode(26,ListNode(18,ListNode(32))))

#在链表中构造环路

def cycle_list(l1):

first=l1

temp=firstfor i in range(3): #向后移动三次,即将20作为入环节点

temp=temp.nextwhilefirst.next:

first=first.next

first.next=tempreturnl1

l3=cycle_list(l1)

#l3.traverse()

#返回入环点

def check_cycle_entrance(head):

slow= fast =head

found_cycle=Falsewhile fast!=None and fast.next!=None and not found_cycle:

fast=fast.next.next

slow=slow.nextif slow isfast: #链表有环路

found_cycle=Trueiffound_cycle:

fast=head #快指针从头结点开始,一次走一步while fast!=slow:

fast=fast.next

slow=slow.nextreturnfastelse:returnNone

cycle_node=check_cycle_entrance(l3)

print(cycle_node.data)

cycle_node=check_cycle_entrance(l2)

print(cycle_node)

返回入环点

(3)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算环的长度?

解题思路: 由上题可知,按照 p2 每次两步,p1 每次一步的方式走,发现 p2 和 p1 重合,确定了单向链表有环路了。接下来,从相遇点继续走,那么当 p1 和 p2 再次相遇的时候,p1走过的长度即为环长度。

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(31,ListNode(26,ListNode(18,ListNode(32))))

#在链表中构造环路

def cycle_list(l1):

first=l1

temp=firstfor i in range(3): #向后移动三次,即将20作为入环节点

temp=temp.nextwhilefirst.next:

first=first.next

first.next=tempreturnl1

l3=cycle_list(l1)

#l3.traverse()

#计算环路长度

def count_cycle_length(head):

slow= fast =head

found_cycle=Falsewhile fast!=None and fast.next!=None and not found_cycle:

fast=fast.next.next

slow=slow.nextif slow isfast: #链表有环路

found_cycle=Trueiffound_cycle:

count= 1fast=fast.next.next

slow=slow.nextwhile fast!=slow: #第二次相遇

fast=fast.next.next

slow=slow.next

count= count+1

returncountelse:returnNone

cycle_length=count_cycle_length(l3)

print(cycle_length)

计算环长度

(4)题目描述:输入一个单向链表,判断链表是否有环。如果链表存在环,计算链表长度?

解题思路:计算出第(2)题中a和第(3)题中的环路长,两者之和即为链表长度

判断链表的公共交点

题目描述:给出两个单向链表的头指针(如下图所示),求链表的交点

解题思路:求出两链表的长度,长链表先走,然后逐个比较两个链表的值,第一个相等的值即为交点。(若只要判断是否相交,只需判断尾节点是否相等)

class ListNode(object):

def __init__(self,data,next=None):

self.data=data

self.next=next

def traverse(self):

temp=selfwhile temp!=None:

print temp.data

temp=temp.next

l1= ListNode(1,ListNode(56,ListNode(8,ListNode(20,ListNode(10,ListNode(12))))))

l2= ListNode(31,ListNode(25,ListNode(10,ListNode(12))))

#判断链表交点

def linkedlist_node(l1,l2):

head1=l1

head2=l2

length1=length2=0

whilehead1:

length1= length1+1head1=head1.nextwhilehead2:

length2= length2+1head2=head2.nextif length1>length2: #长链表先走for i in range(length1-length2):

l1=l1.nextelse:for i in range(length2-length1):

l2=l2.nextwhile l1!=None and l2!=None:if l1.data = l2.data: #应该是l1==l2(或l1 isl2),这里使用值代替了,方便看执行结果returnl1.data

l1=l1.next

l2=l2.nextreturnNone

print(linkedlist_node(l1,l2))

链表交点

2,有序列表(Ordered List)

有序列表和无序列表结构相同,只是列表中的数据按顺序排列(升序或降序),其常用操作也基本相同。

常用操作

Llist =OrderedList()

add(item)

remove(item)

search(item)

pop()

pop(pos)

index(item)

size()

isEmpty()

python 实现有序列表

pop(), index(item), size()和isEmpty()方法和UnorderedList相同,add(item), search(item)和remove(item)代码如下所示:

classOrderedList(object):def __init__(self):

self.head=Nonedefadd(self,item):

previous=None

current=self.headwhile current and (item >current.getData()):

previous=current

current=current.getNext()

temp=Node(item)if previous ==None:

temp.setNext(self.head)

self.head=tempelse:

previous.setNext(temp)

temp.setNext(current)defsearch(self,item):

current=self.head

found=False

stop=Falsewhile current!=None and (not found) and (notstop):if current.getNext()==item:

found=Trueelse:if current.getData()

current=current.getNext()else:

stop=Truereturnfounddefremove(self,item):

previous=None

current=self.headwhile current and (item!=current.getData()):

previous=current

current=current.getNext()if current!=None:if previous ==None:

self.head=current.getNext()else:

previous.setNext(current.getNext())else: #self.head=None或者item不存在链表中

raise ValueError('%s item is not in the OrderedList'%item)

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值