简体   繁体   English

原来的链表改变了

[英]Original linked list changed

The original linked list in main changes once I try to reverse the second half of the link list but I do not understand how exactly.一旦我尝试反转链接列表的后半部分,主要更改中的原始链接列表,但我不明白具体如何。 If anyone can give me an explanation in detail I will greatly appreciate it.如果有人能给我详细的解释,我将不胜感激。 I left some comments in the code explaining where I am not sure what is going on.我在代码中留下了一些注释,解释了我不确定发生了什么。

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()

I have some comment above explaining an issue I have with my understanding of what is going on.我在上面有一些评论,解释了我对正在发生的事情的理解的一个问题。 My initial thought was to just have a variable that has the reverse second half of the link list and the rest of the code without reverting back to the original order of the link list.我最初的想法是只拥有一个变量,该变量具有链接列表的反向后半部分和其余代码,而不恢复到链接列表的原始顺序。 This does not work because when I call is_palindromic_linked_list(head) for the second time in main the link list has been modified and does not have the attribute .next这不起作用,因为当我在 main 中第二次调用is_palindromic_linked_list(head)时,链接列表已被修改并且没有属性.next

To my understanding the variable slow is a pointer that points to the memory address of the start of the second half of the link list, therefore, when I reverse the second half of the linked list the my original linked list get modified as well?据我了解, slow变量是一个指向链接列表后半部分开头的内存地址的指针,因此,当我反转链接列表的后半部分时,我的原始链接列表也会被修改吗? If this is the case, then what is happening in detail because I am having trouble understanding how reverting the reversal somehow keeps the original linked list untouched in main.如果是这种情况,那么详细发生了什么,因为我无法理解如何恢复反转以某种方式使原始链表在 main 中保持不变。 What I mean by this is that in my main function if I were to print out each node from link list head without reverting back the reversal in is_palindromic_linked_list function the link list is changed and therefore at some point does not contain the .next so the second time I call this function an error occurs but by reversing back the linked list it works.我的意思是,在我的main函数中,如果我要打印出链接列表头中的每个节点而不恢复is_palindromic_linked_list函数中的反转,链接列表会发生更改,因此在某些时候不包含.next所以第二个当我调用这个函数时会发生错误,但是通过反转链接列表它可以工作。

I do understand that addresses are involved but I do not exactly see what is happening here because I see it as I detached the second half of the linked list so whatever I do to this link list I thought would be completely separate to the original, so what I mean is by detaching it I can see how my original link list now only contains the first half and reversing back again this detached link list (that I believe has nothing to do with my original linked list now) somehow keeps my original linked list as it was at first.我确实知道涉及到地址,但我并没有完全看到这里发生了什么,因为我在分离链接列表的后半部分时看到它,所以无论我对此链接列表做什么,我认为都将与原始链接完全分开,所以我的意思是通过分离它我可以看到我的原始链接列表现在如何只包含前半部分并再次反转这个分离的链接列表(我认为现在与我的原始链接列表无关)以某种方式保留了我的原始链接列表就像一开始一样。

I'm not sure if I make sense.我不确定我是否有道理。 I'm struggling to explain my thought process and would really like some clarification.我正在努力解释我的思考过程,并且非常希望得到一些澄清。

when I reverse the second half of the linked list the my original linked list get modified as well?当我反转链表的后半部分时,我的原始链表也会被修改吗?

Yes, as the collection of nodes is the same: no new nodes are created, only modified (their next attribute).是的,因为节点的集合是相同的:不创建新节点,只修改(它们的next属性)。 So when in the second half of the list you modify nodes, then of course this affects the list.因此,当您在列表的后半部分修改节点时,这当然会影响列表。

It can help to visualise the list.它可以帮助可视化列表。 Let's take for example a list that has values 1, 2, 3, 4, 5 and 6:让我们以一个值为 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│
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘

After executing head_second_half = reverse(slow) , we have this situation:执行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 | 
└─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘  └─────────┘

So if now you were to iterate the list that starts at head , you would get 1,2,3,4.因此,如果现在您要迭代从head开始的列表,您将得到 1,2,3,4。 You cannot reach nodes 5 and 6 anymore when starting at head , because the node at 4 has been made a tail node, ie it has no next .head开始时,您无法再到达节点 5 和 6,因为 4 处的节点已成为尾节点,即它没有next Obviously it cannot at the same time be a tail for the second half, and also a node that still connects to the node with value 5. It can only be in one state.显然它不能同时是后半部分的尾部,并且也是一个仍然连接到值为5的节点的节点。它只能处于一种状态。 And so that is how it truncates the original list.这就是它截断原始列表的方式。

By reversing a second time, you restore the list to its original state.通过第二次反转,您可以将列表恢复到其原始状态。

Recall that during this process there are just those 6 nodes.回想一下,在这个过程中只有那 6 个节点。 No other nodes are created, or copied.不会创建或复制其他节点。 Only those 6 exist.只有这6个存在。 The only thing that happens is that several variables are used to reference certain nodes, and that some nodes get a different next value, but we keep working with the given 6 nodes.唯一发生的事情是使用多个变量来引用某些节点,并且某些节点获得不同的next值,但我们继续使用给定的 6 个节点。 There is no copy.没有副本。

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

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