https://blog.csdn.net/sf9898/article/details/104946291
ll = Link()
# 先构建测试用的链表
for i in range(5):
ll.addFront(i)
ll.addFront(100)
ll.addBack(250)
for i in range(5):
ll.addBack(i)
# 到目前为止是一串没有环的链表
ll.travel() # 100 4 3 2 1 0 250 0 1 2 3 4
# class Link的方法
def getLastNode(self):
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
return pre
def getNode(self, item):
cur = self.__head
res = None
while cur:
if cur.item == item:
res = cur
break
else:
cur = cur.next
return res
ll = Link()
# 先构建测试用的链表
for i in range(5):
ll.addFront(i)
ll.addFront(100)
ll.addBack(250)
for i in range(5):
ll.addBack(i)
# 到目前为止是一串没有环的链表
ll.travel() # 100 4 3 2 1 0 250 0 1 2 3 4
# 接下来构建有环的链表
# 设置一个函数getLastNode使得我们可以取到链表的最后一个节点(这个例子中就是4这个节点),
# 然后将它的next指向250的这个节点(又要有个函数能够取到这个节点,因此有了getNode这个函数),这样就可以形成环了
# print(ll.getNode(250).item) # 这一行用来验证getNode 函数的正确性,应打印250
ll.getLastNode().next = ll.getNode(250)
ll.travel() # 事实上现在遍历一下就可以发现事情不简单了
def hasLoop(self):
if self.__head is None:
return False
# 能到这说明头结点不是空的,但是有可能只有一个节点,也有可能 N个(N > 1)
aNode = self.__head
bNode = self.__head
res = False
# 2个结点,往前跑,一个跑的快,一个跑的慢,如果没有环,慢的结点不会追上快的
# 如果有环,肯定有一个时刻,快的点绕回来追上了慢的点
# 如果只有一个或两个结点,则不会进行下面的循环,直接返回False (res)
while bNode.next and bNode.next.next:
bNode = bNode.next.next # 这里用B结点代表跑的快的,A是跑的慢的
aNode = aNode.next
if bNode == aNode:
res = True
break
return res
测试一下,完整代码:
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
class Link(object):
def __init__(self):
self.__head = None
def isEmpty(self):
return self.__head is None
# 头部插入
def addFront(self, item):
node = Node(item)
node.next = self.__head
self.__head = node
# 尾部插入
def addBack(self, item):
node = Node(item)
if self.__head is None:
self.__head = node
return
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
# 当cur 为最后一个节点时带入,pre更新为最后一个节点,cur更新为最后一个节点的下一个节点即为空,
# 下一次while cur 时会退出循环,此时的pre表示的就是最后一个节点,将node挂到pre的后面即可
pre.next = node
def size(self):
count = 0
cur = self.__head
while cur:
count += 1
cur = cur.next
return count
def travel(self):
cur = self.__head
while cur:
print(cur.item, end=' ')
cur = cur.next
print('')
# 删除头部节点
def removeFront(self):
cur = self.__head
self.__head = self.__head.next
cur.next = None
# 删除尾部节点
def removeBack(self):
# 空节点时
if self.__head is None:
return
# 只有一个节点
if self.__head and self.__head.next is None:
self.__head = None
return
# 链表节点有两个及以上
cur = self.__head # 当前节点
pre = None # 前一个节点
cn = cur.next # 后一个节点
# 刚开始cur取到的是第一个节点,cn是第二个
while cn:
pre = cur
cur = cur.next
cn = cur.next
pre.next = None
def getLastNode(self):
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
return pre
def getNode(self, item):
cur = self.__head
res = None
while cur:
if cur.item == item:
res = cur
break
else:
cur = cur.next
return res
def hasLoop(self):
if self.__head is None:
return False
# 能到这说明头结点不是空的,但是有可能只有一个节点,也有可能 N个(N > 1)
aNode = self.__head
bNode = self.__head
res = False
# 2个结点,往前跑,一个跑的快,一个跑的慢,如果没有环,慢的结点不会追上快的
# 如果有环,肯定有一个时刻,快的点绕回来追上了慢的点
# 如果只有一个或两个结点,则不会进行下面的循环,直接返回False
while bNode.next and bNode.next.next:
bNode = bNode.next.next # 这里用B结点代表跑的快的,A是跑的慢的
aNode = aNode.next
if bNode == aNode:
res = True
break
return res
ll = Link()
# 先构建测试用的链表
for i in range(5):
ll.addFront(i)
ll.addFront(100)
ll.addBack(250)
for i in range(5):
ll.addBack(i)
# 到目前为止是一串没有环的链表
ll.travel() # 100 4 3 2 1 0 250 0 1 2 3 4
# 接下来构建有环的链表
# 设置一个函数getLastNode使得我们可以取到链表的最后一个节点(这个例子中就是4这个节点),
# 然后将它的next指向250的这个节点(又要有个函数能够取到这个节点,因此有了getNode这个函数),这样就可以形成环了
# print(ll.getNode(250).item) # 这一行用来验证getNode 函数的正确性,应打印250
ll.getLastNode().next = ll.getNode(250) # 注释掉这行,就无法形成环了,这时下面的打印结果应是False
# ll.travel() # 事实上现在遍历一下就可以发现事情不简单了
print(ll.hasLoop())
def hasLoop(self):
if self.__head is None:
return False
# 能到这说明头结点不是空的,但是有可能只有一个节点,也有可能 N个(N > 1)
if self.__head and self.__head.next is None:
# 只有一个头结点,不认为是环
return False
# 能到这里就说明,至少有2个节点了
# 有两个及以上结点,这里第二个节点的next指向None可以说明没有环,否则这里就有可能会出现环
if self.__head.next.next == self.__head:
# 如果第二个节点的next指向第一个节点则认为是环,否则可能是指向空或者是下一个节点
return True
aNode = self.__head
bNode = self.__head
res = False
# 设置2个结点,往前跑,一个跑的快,一个跑的慢,如果没有环,慢的结点不会追上快的
# 如果有环,肯定有一个时刻,快的点绕回来追上了慢的点
# 如果只有两个结点(也就是说第二个节点的next指向None),则不会进行下面的循环,直接返回False
while bNode.next and bNode.next.next:
bNode = bNode.next.next # 这里用B结点代表跑的快的,A是跑的慢的
aNode = aNode.next
if bNode == aNode:
res = True
break
return res
class Node(object):
def __init__(self, item):
self.item = item
self.next = None
class Link(object):
def __init__(self):
self.__head = None
def isEmpty(self):
return self.__head is None
# 头部插入
def addFront(self, item):
node = Node(item)
node.next = self.__head
self.__head = node
# 尾部插入
def addBack(self, item):
node = Node(item)
if self.__head is None:
self.__head = node
return
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
# 当cur 为最后一个节点时带入,pre更新为最后一个节点,cur更新为最后一个节点的下一个节点即为空,
# 下一次while cur 时会退出循环,此时的pre表示的就是最后一个节点,将node挂到pre的后面即可
pre.next = node
def size(self):
count = 0
cur = self.__head
while cur:
count += 1
cur = cur.next
return count
def travel(self):
cur = self.__head
while cur:
print(cur.item, end=' ')
cur = cur.next
print('')
# 删除头部节点
def removeFront(self):
cur = self.__head
self.__head = self.__head.next
cur.next = None
# 删除尾部节点
def removeBack(self):
# 空节点时
if self.__head is None:
return
# 只有一个节点
if self.__head and self.__head.next is None:
self.__head = None
return
# 链表节点有两个及以上
cur = self.__head # 当前节点
pre = None # 前一个节点
cn = cur.next # 后一个节点
# 刚开始cur取到的是第一个节点,cn是第二个
while cn:
pre = cur
cur = cur.next
cn = cur.next
pre.next = None
def getLastNode(self):
cur = self.__head
pre = None
while cur:
pre = cur
cur = cur.next
return pre
def getNode(self, item):
cur = self.__head
res = None
while cur:
if cur.item == item:
res = cur
break
else:
cur = cur.next
return res
def hasLoop(self):
if self.__head is None:
return False
# 能到这说明头结点不是空的,但是有可能只有一个节点,也有可能 N个(N > 1)
if self.__head and self.__head.next is None:
# 只有一个头结点,不认为是环
return False
# 能到这里就说明,至少有2个节点了
# 有两个及以上结点,这里第二个节点的next指向None可以说明没有环,否则这里就有可能会出现环
if self.__head.next.next == self.__head:
# 如果第二个节点的next指向第一个节点则认为是环,否则可能是指向空或者是下一个节点
return True
aNode = self.__head
bNode = self.__head
res = False
# 设置2个结点,往前跑,一个跑的快,一个跑的慢,如果没有环,慢的结点不会追上快的
# 如果有环,肯定有一个时刻,快的点绕回来追上了慢的点
# 如果只有两个结点(也就是说第二个节点的next指向None),则不会进行下面的循环,直接返回False
while bNode.next and bNode.next.next:
bNode = bNode.next.next # 这里用B结点代表跑的快的,A是跑的慢的
aNode = aNode.next
if bNode == aNode:
res = True
break
return res
ll = Link()
# # 先构建测试用的链表
# for i in range(5):
# ll.addFront(i)
# ll.addFront(100)
# ll.addBack(250)
# for i in range(5):
# ll.addBack(i)
# # 到目前为止是一串没有环的链表
# ll.travel() # 100 4 3 2 1 0 250 0 1 2 3 4
# # 接下来构建有环的链表
# # 设置一个函数getLastNode使得我们可以取到链表的最后一个节点(这个例子中就是4这个节点),
# # 然后将它的next指向250的这个节点(又要有个函数能够取到这个节点,因此有了getNode这个函数),这样就可以形成环了
#
# # print(ll.getNode(250).item) # 这一行用来验证getNode 函数的正确性,应打印250
#
# # ll.getLastNode().next = ll.getNode(250)
# # ll.travel() # 事实上现在遍历一下就可以发现事情不简单了
# print(ll.hasLoop())
# 一种特殊的情况,只有两个结点,但是形成环
ll.addBack(1)
ll.addBack(2)
ll.getLastNode().next = ll.getNode(1)
print(ll.hasLoop()) # 现在结果应该是True