【问题标题】:Linked List Delete Method链表删除方法
【发布时间】:2014-02-15 19:03:03
【问题描述】:

以下是我的链接列表的类定义。我运行一个测试程序,它创建一个新的 LinkedList 并插入数字“3、2、1”,然后打印该列表。这工作正常。但是,当我尝试删除“3”或“2”时,删除方法永远不会完成。当我尝试删除“1”时,它只会打印出完整的列表,就好像什么都没有被删除一样。

public class LinkedListTest implements LinkedList {
private Node head;

public LinkedListTest(){
    head = new Node();
}

public void insert(Object x){
    if (lookup(x).equals(false)){

        if (head.data == null)
            head.data = x;

        else{
            //InsertLast
            Node temp = head;

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

            Node NewNode = new Node();
            NewNode.data = x;
            NewNode.next = null;

            temp.next = NewNode;

        }
    }
    //Runtime of insert method will be n, where n is the number of nodes
}

public void delete(Object x){
    if (lookup(x).equals(true)){
        if (head.data == x)
            head = head.next;

        else{
            Node temp = head;
            while (temp.next != null){
                if ((temp.next).data == x)
                    temp.next = (temp.next).next;
                else
                    temp = temp.next;
            }
        }

    }
}

public Object lookup(Object x){
    Node temp = head;
    Boolean search = false;

    if (head.data == x)
        search = true;

    while (temp.next != null){
        if (temp.data == x){
            search = true;
        }

        else{
            temp = temp.next;
        }
    }

    return search;
}

public boolean isEmpty(){
    if (head.next == null && head.data == null)
        return true;
    else
        return false;
}

public void printList(){
    Node temp = head;
    System.out.print(temp.data + " ");

    while (temp.next != null){
        temp = temp.next;
        System.out.print(temp.data + " ");
    }

}
}

编辑:这是节点类:

public class Node {
public Object data;
public Node next;

public Node(){
    this.data = null;
    this.next = null;
}
}

【问题讨论】:

    标签: java list


    【解决方案1】:

    这里有几个问题。

    第一个大问题是,在您的 lookup() 和您的 delete() 方法中,当成功条件发生时,您不会跳出循环。这就是您的程序挂起的原因;它处于无限循环中。

    还有一点值得注意的是,在所有 if/else 语句中不要使用花括号是一种非常糟糕的做法。没有理由不这样做,而且如果你不这样做,它很容易引入错误。

    lookup() 你应该有:

    if (head.data == x) {
        search = true;
    } else {
        while (temp.next != null){
            if (temp.data == x){
                search = true;
                break;
            } else {
                temp = temp.next;
            }
        }
    }
    

    delete():

    if (head.data == x) {
        head = head.next;
    } else {
        Node temp = head;
        while (temp.next != null) {
            if (temp.next.data.equals(x)) {
                temp.next = temp.next.next;
                break;
            } else {
                temp = temp.next;
            }
        }
    }
    

    现在这将产生你所期望的:

    public static void main( String[] args ) 
    {
       LinkedListTest llt = new LinkedListTest();
    
       llt.insert(1);
       llt.insert(2);
       llt.insert(3);
    
       llt.printList();
       System.out.println();
    
       llt.delete(2);
       llt.printList();
    }
    

    输出:

    1 2 3
    1 3

    但是,这不会暴露您的第二个更大的问题。查看节点的data 时,您正在使用== 比较参考值

    由于自动装箱小整数值的副作用,这目前“有效”;你得到相同的对象引用。 (由于字符串池,字符串文字也可以“工作”)。有关这方面的更多信息,请查看 How do I compare Strings in JavaWhen comparing two integers in java does auto-unboxing occur

    让我们看看这个:

    public static void main( String[] args )
    {
       LinkedListTest llt = new LinkedListTest();
    
       llt.insert(1000);
       llt.insert(2000);
       llt.insert(2000);
       llt.insert(3000);
    
       llt.printList();
       System.out.println();
    
       llt.delete(2000);
       llt.printList();
    }
    

    输出:

    1000 2000 2000 3000
    1000 2000 2000 3000

    lookup() 停止工作,允许插入副本。 delete() 也停止工作。

    这是因为 int 值超过 127 自动框为唯一的 Integer 对象而不是缓存对象(请参阅上面链接的 SO 问题以获取完整说明)。

    您使用== 来比较data 持有的值的任何地方都需要改为使用.equals()

    if (temp.data.equals(x)) {
    

    解决了这些技术问题后,您的程序就可以运行了。不过,您还应该考虑其他一些事情。直接跳出来的两个是:

    • lookup 应该返回 boolean
    • 无需在delete() 中调用lookup()
    • lookup 本身作为单独的方法是一种相当低效的方法;插入遍历整个列表两次。

    【讨论】:

    • 我最初使用 .equals,但有人告诉我这是不正确的。这似乎非常错误。我还认为查找应该是一个布尔值,我不需要在删除中查找,但它是实验室的一部分,这就是我被告知做事的方式。最后,感谢这个很棒的答案!这非常有帮助!
    • @ChristianBaker 很高兴我能帮上忙。我讨厌看到这样的赋值,因为......是的,它们太可怕了:-D 但最后重要的是要理解持有 Object 引用值的变量与 C 中的指针基本相同;它们包含一个引用内存中某物的值。如果您想知道两个变量是否引用内存中的同一个对象,请使用==。如果您想知道内存中的两个对象是否因其包含的内容而被视为相等,请使用.equals()
    • 最后一个问题,可以说 if (head.data == null) 吗?
    • @ChristianBaker 是的。 null 实际上是一个(特殊的)参考值。这意味着该变量没有保存对内存中对象的引用(这是您正在检查的内容)。
    【解决方案2】:

    首先为什么查找返回一个对象?将其更改为布尔值。 lookup() 中的“while”循环也没有前进。您需要删除“其他”。 不过,您的删除功能似乎还不错。

    【讨论】:

      【解决方案3】:

      我觉得你有些地方搞错了。

      首先,当您使用 LinkedList 时,您尝试实现的所有功能都已经存在。

      而且你的风格比较差。例如,为什么要使用 WrapperClass 布尔值进行查找?

      contains 之类的功能与 get 之类的功能结合在一个方法中并不是一个好主意。将其拆分为两种方法,让 contains 只返回一个布尔值并测试列表中是否存在元素。让我们搜索并返回一个元素。

      除此之外,您还尝试通过相等来比较对象。如果您没有覆盖 equals,则永远不能删除任何内容,因为 equals 需要引用相等,而这在大多数情况下都不会给出。

      我强烈建议您购买 Java 书籍或其他东西来提高您的整体知识..

      【讨论】:

      • 这是实验室的一部分。我被要求创建自己的链表实现,我必须实现一个查找返回布尔值的接口。
      • 是的,但是您的查找方法只返回一个布尔包装类,而不是布尔值(原始数据类型)。查找的签名应该是 boolean lookup(Object x) 并且搜索的声明/初始化应该像这样 boolean search = false; 这将创建一个布尔(原始数据类型) 而不是布尔值(包装类)
      • Welp,我很愚蠢。感谢您指出了这一点。不知道为什么我让它返回一个布尔值。
      猜你喜欢
      • 2012-03-23
      • 2012-09-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多