如何判斷鍊錶是否有環 鍊錶是否有環的判斷

2021-10-12 09:24:48 字數 3887 閱讀 9967

對於鍊錶是否存在環,有三個問題需要考慮:

1. 是否有環

2. 入環節點

3. 環的長度

第一種方法快慢指標法,也稱之為龜兔演算法,設定兩個指標,慢指標和快指標。最開始均指向鍊錶的頭節點,之後,快指標每次後移兩個節點,慢指標每次後移乙個節點。

1. 如果快指標指向空,則鍊錶無環

2. 若快指標和慢指標再次指向乙個相同節點,則證明鍊錶有環

入環節點:

記快慢指標首次在節點i處相遇,即二者均指向節點i。令慢指標指向鍊錶的頭節點h,

之後,慢指標和快指標同時移動,每次後移乙個指標,第乙個相遇的節點就是環的起點。

環的長度,兩種方法:

法1. 求入環節點時,在慢指標指向煉表頭節點、快指標指向節點i時,設定整型變數length = 0, 之後直至快慢指標相遇,二者每同時移動一次,lenght增加1。相遇後,length + 1 即環的長度。

法2. 在快慢指標指向相同的節點i時,設定 length = 0, 快指標仍每次後移兩個節點,慢指標每次後移乙個節點,快慢指標同時移動後, length增加1。 快慢指標再次相遇時,length即為環的長度。

對於思路可以進一步參閱:

第二種方法: brent's algorithm

例子:python 實現**:

# python program to implement

# brent's cycle detection

# algorithm to detect cycle

# in a linked list.

# node class

class node:

# constructor to initialize

# the node object

def __init__(self, data):

self.data = data

self.next = none

class linkedlist:

# function to initialize head

def __init__(self):

self.head = none

# function to insert a new node

# at the beginning

def push(self, new_data):

new_node = node(new_data)

new_node.next = self.head

self.head = new_node

# utility function to prit

# the linked linkedlist

def printlist(self):

temp = self.head

while(temp):

print(temp.data, end=" ")

temp = temp.next

def detectcycle(self):

# if head is null

# then no loop

temp = self.head

if not (temp):

return false

first_p = temp

second_p = temp.next

power = 1

length = 1

# this loop runs till we

# find the loop. if there

# is no loop then second

# pointer ends at null

while (second_p and second_p != first_p):

# condition after which

# we will update the power

# and length as smallest

# power of two gives

# the start of cycle.

if (length == power):

# updating the power.

power *= 2

# updating the length

length = 0

first_p = second_p

second_p = second_p.next

length = length+1

# if it is null then no loop

if not (second_p):

return

# otherwise length stores

# actual length of loop.

# if needed, we can also

# print length of loop.

# print("length of loop is ")

# print (length)

# now set first_pointer

# to the beginning and

# second_pointer to

# beginning plus cycle

# length which is length.

first_p = second_p = self.head

while (length > 0):

second_p = second_p.next

length = length-1

# now move both pointers

# at same speed so that

# they meet at the

# beginning of loop.

while (second_p != first_p):

second_p = second_p.next

first_p = first_p.next

return first_p

# driver program for testing

llist = linkedlist()

llist.push(5)

llist.push(4)

llist.push(3)

llist.push(2)

llist.push(1)

# create a loop for testing

node = llist.head

while node.next:

node = node.next

node.next = llist.head.next

res = llist.detectcycle()

if(res.data):

print("loop found at ", end=' ')

print(res.data)

else:

print("no loop ")

第二種方法的優點在於:

1)在第乙個迴圈檢測是否存在環時, 也找到環的長度。

2)我們在每次迭代中只移動快指標,而避免移動第乙個指標,減少移動次數。

對於最開始提到的三個問題,對於入環的節點的思路 和 快慢指標方法中求環的長度的第一種處理思路 是共通的。

這裡是,已知環的長度,求入環節點,而快慢指標是已知環的節點求環的長度。 二者可以對比著看。

第三種做法:

遍歷鍊錶,將鍊錶的位址儲存在列表中,對於當前遍歷的節點,如果在列表中已經存在,則有環,且可以求出環的長度和入環節點。

如果鍊錶全部遍歷直至來鍊錶為空,則證明沒有環。

今天在看**的時候,偶然查到floyd's algorithm, 偶然看到這個問題。 10.10, 希望自己會更好。少無謂的道歉,多幾分滿意的感激。

如何判斷鍊錶是否有環

背景 例如在乙個大的系統中,如果出現兩個鍊錶相交的情況,而且釋放其中乙個鍊錶所有的節點,那就會造成資訊的丟失,並且釋放其中乙個鍊錶的所有節點,那就會造成資訊的丟失並且與之相交的鍊錶也會受到影響,如下圖 給出兩個單鏈表的頭指標 h1,h2 假設兩個鍊錶均不帶環 方法一 判斷第乙個鍊錶所有的節點是否在第...

如何判斷鍊錶是否有環

這個問題可以衍生出很多擴充套件性的問題 給定乙個單鏈表,1.如何判斷是否有環 2.如何知道環的長度 3.如何找到環的入口 4.整個鍊錶的長度是多少 相應的解法如下 問題1時後面所有問題的根問題,解決這個問題一般用到快慢指標,乙個fast指標,乙個slow指標,兩個指標同時指向單鏈表的頭結點,然後fa...

判斷鍊錶是否有環

1.如何判斷是否有環?如果有兩個頭結點指標,乙個走的快,乙個走的慢,那麼若干步以後,快的指標總會超過慢的指標一圈。2.如何計算環的長度?第一次相遇 超一圈 時開始計數,第二次相遇時停止計數。3.如何判斷環的入口點 碰撞點p到連線點的距離 頭指標到連線點的距離,因此,分別從碰撞點 頭指標開始走,相遇的...