繁体   English   中英

原来的链表改变了

[英]Original linked list changed

一旦我尝试反转链接列表的后半部分,主要更改中的原始链接列表,但我不明白具体如何。 如果有人能给我详细的解释,我将不胜感激。 我在代码中留下了一些注释,解释了我不确定发生了什么。

class Node:
  def __init__(self, value, next=None):
    self.value = value
    self.next = next



def is_palindromic_linked_list(head):  
  if head is None or head.next is None:
    return True

  # find middle of the LinkedList
  slow, fast = head, head
  while (fast is not None and fast.next is not None):
    slow = slow.next
    fast = fast.next.next

  '''
  Here I reverse the second half of the link list.

  The variable slow points to the second half of the link list and
  the reversed linked list is now head_second_half.
  
  If I print out each node, in link list head, every node prints out from the
  original link list on this line before the reversal.
  '''

  head_second_half = reverse(slow)  # reverse the second half
  # store the head of reversed part to revert back later

  '''
  Here although I am passing slow into the reverse function to reverse the second
  half of the link list my link list head gets modified and I can see this because
  by printing out all nodes from link list head on this line after the reversal I
  seem to only get the first half of the link list 
  '''

  copy_head_second_half = head_second_half

  # compare the first and the second half
  while (head is not None and head_second_half is not None):
    if head.value != head_second_half.value:
      break  # not a palindrome

    head = head.next
    head_second_half = head_second_half.next

  reverse(copy_head_second_half)  # revert the reverse of the second half
  
  if head is None or head_second_half is None:  # if both halves match
    return True

  return False

def reverse(head):
  prev = None
  while (head is not None):
    next = head.next
    head.next = prev
    prev = head
    head = next
  return prev


def main():
  head = Node(2)
  head.next = Node(4)
  head.next.next = Node(6)
  head.next.next.next = Node(4)
  head.next.next.next.next = Node(2)

  print("Is palindrome: " + str(is_palindromic_linked_list(head)))

  head.next.next.next.next.next = Node(2)
  print("Is palindrome: " + str(is_palindromic_linked_list(head)))


main()

我在上面有一些评论,解释了我对正在发生的事情的理解的一个问题。 我最初的想法是只拥有一个变量,该变量具有链接列表的反向后半部分和其余代码,而不恢复到链接列表的原始顺序。 这不起作用,因为当我在 main 中第二次调用is_palindromic_linked_list(head)时,链接列表已被修改并且没有属性.next

据我了解, slow变量是一个指向链接列表后半部分开头的内存地址的指针,因此,当我反转链接列表的后半部分时,我的原始链接列表也会被修改吗? 如果是这种情况,那么详细发生了什么,因为我无法理解如何恢复反转以某种方式使原始链表在 main 中保持不变。 我的意思是,在我的main函数中,如果我要打印出链接列表头中的每个节点而不恢复is_palindromic_linked_list函数中的反转,链接列表会发生更改,因此在某些时候不包含.next所以第二个当我调用这个函数时会发生错误,但是通过反转链接列表它可以工作。

我确实知道涉及到地址,但我并没有完全看到这里发生了什么,因为我在分离链接列表的后半部分时看到它,所以无论我对此链接列表做什么,我认为都将与原始链接完全分开,所以我的意思是通过分离它我可以看到我的原始链接列表现在如何只包含前半部分并再次反转这个分离的链接列表(我认为现在与我的原始链接列表无关)以某种方式保留了我的原始链接列表就像一开始一样。

我不确定我是否有道理。 我正在努力解释我的思考过程,并且非常希望得到一些澄清。

当我反转链表的后半部分时,我的原始链表也会被修改吗?

是的,因为节点的集合是相同的:不创建新节点,只修改(它们的next属性)。 因此,当您在列表的后半部分修改节点时,这当然会影响列表。

它可以帮助可视化列表。 让我们以一个值为 1、2、3、4、5 和 6 的列表为例:

 head                                   slow
  ↓                                      ↓ 
┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│value: 1 │  │value: 2 │  │value: 3 │  │value: 4 │  │value: 5 │  │value: 6 │  
│next: —————→│next: —————→│next: —————→│next: —————→│next: —————→│next:None│
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘

执行head_second_half = reverse(slow) ,我们有这样的情况:

 head                                   slow                   head_second_half
  ↓                                      ↓                         ↓           
┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐  ┌─────────┐
│value: 1 │  │value: 2 │  │value: 3 │  │value: 4 │  │value: 5 │  │value: 6 │  
│next: —————→│next: —————→│next: —————→│next:None│←—————:next │←—————:next | 
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘

因此,如果现在您要迭代从head开始的列表,您将得到 1,2,3,4。 head开始时,您无法再到达节点 5 和 6,因为 4 处的节点已成为尾节点,即它没有next 显然它不能同时是后半部分的尾部,并且也是一个仍然连接到值为5的节点的节点。它只能处于一种状态。 这就是它截断原始列表的方式。

通过第二次反转,您可以将列表恢复到其原始状态。

回想一下,在这个过程中只有那 6 个节点。 不会创建或复制其他节点。 只有这6个存在。 唯一发生的事情是使用多个变量来引用某些节点,并且某些节点获得不同的next值,但我们继续使用给定的 6 个节点。 没有副本。

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM