【问题标题】:why does one method destroy my linked list while another does not?为什么一种方法会破坏我的链表,而另一种则不会?
【发布时间】:2021-10-20 16:13:34
【问题描述】:

我看到有人问过类似的问题,但没有一个答案能真正解决我的困惑。

我正在研究一些链表内容,尝试编写方法来解决类似 leetcode 的问题。我正在使用单链表,定义为:

public class LinkedListy {
ListNode head;
LinkedListy(){};

   public static class ListNode { 
      int val; //integer variable
      ListNode next; //pointer

      ListNode() {} 

      ListNode(int val) { 
          this.val = val; 
      }

      ListNode(int val, ListNode next) { 
          this.val = val; this.next = next; 
      }
  }
  ...

我正在尝试编写一个函数来反转我的链表,但不会破坏我的原始链表。我编写的代码可以反转列表,但会破坏原始列表:

public ListNode reverse() {
    //use copyList function to avoid altering head --> DOESN'T WORK
    ListNode current = head;
    ListNode temp = null;
    ListNode copied_result = null;

    while(current != null){
        temp = current.next;
        current.next = copied_result;
        copied_result = current;
        current = temp;
    }
    return copied_result;
}

通过阅读此处和其他地方,我了解到通过设置 current = head,我只是为同一个 ListNode 创建了一个新引用。因此,当我运行我的代码时,我正在改变原始列表。

主要困惑:我很困惑,因为我编写的方法不会破坏原始列表,而是使用相同类型的 head 引用。例如,在我的“length()”中方法,我设置 dummy = head 并更改 dummy 以查找列表的长度。但是,原始列表并没有改变(我写了一个打印函数来打印列表,我验证它在调用 length() 之前和之后打印相同。)

    public int length() {
    ListNode dummy = head;
    int length = 0;
    while(dummy != null) {
        dummy = dummy.next;
        length++;
    }
    return length;
}

所以,我显然不了解 LinkedLists 的一些基本知识。

  1. 为什么我的 reverse() 方法会破坏原始列表,而我的 length() 方法不会?
  2. 是否只有在不破坏原始列表的情况下为链表编写反向方法以在您的 main 方法中复制原始列表并反向复制?

任何帮助或资源将不胜感激。谢谢!

【问题讨论】:

  • current.next = copied_result;next 写入一个值,而dummy = dummy.next; 只是从next 读取而不影响该值。

标签: java linked-list singly-linked-list


【解决方案1】:

length 方法中,您使用名为dummy 的本地可访问变量来遍历列表中的节点;当您设置dummy = dummy.next 时,这会将局部变量的值设置为引用next 节点。这与 dummy.next = null 之类的操作非常不同,后者会影响 dummy 当前所指节点的内容。

为此,您的 reverse 方法实际上并没有“破坏”原始列表 - 主要问题是当您完成时 head 没有被设置为第一个元素。因此,head 仍然“指向”它在函数启动之前所做的同一节点,现在是最后一个节点。

如果您想就地反转列表,那么只需在函数末尾正确更新 head 即可正常工作 - 如果您想返回原始列表的反转副本而不修改原始列表,您将需要复制所有节点。请参阅@Hank_interprize 对深/浅拷贝的描述。

【讨论】:

  • 啊,谢谢!我现在完全可以看到这两种方法之间的区别——更改变量引用的内容与更改实际节点。我会试试你最后更新头部的建议
【解决方案2】:

我认为这里的问题是您实际上并没有将任何新信息复制到新列表中,而是代码只是使用与以前相同的列表以新名称。这可以通过深拷贝来完成。

要创建新列表,您需要将旧数据复制到具有全新指针系统的新列表中,并且只需将数据复制到新链表中,这与复制指针不同。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2019-05-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-20
    • 1970-01-01
    • 2021-06-11
    相关资源
    最近更新 更多