【问题标题】:How to recursively removing an item from linkedList?如何递归地从linkedList中删除一个项目?
【发布时间】:2020-04-18 08:14:05
【问题描述】:

以递归方式实现LinkedList 对我来说有点挑战,我在实现其remove 方法时遇到了困难,想知道如何以递归方式保持对前一项的引用?

MyLinkedList 类

package linkedlist;

public class MyLinkedList {
private Integer value;
private MyLinkedList next;

public MyLinkedList() {
}

public MyLinkedList(Integer value) {
    this.value = value;
}

public void add(Integer value) {
    if (this.value == null) {
        this.value = value;
    } else if (this.next == null) {
        this.next = new MyLinkedList(value);
    } else {
        this.next.add(value);
    }
}

public MyLinkedList remove(Integer index) {
//
//        if (index < 0) {
//            return this;
//        }
//        if (index == 0) {
//            return this.next;
//        }
//        this.next = remove(index - 1);
    return this;
}

public Integer indexOf(Integer value) {
    if (this.value.equals(value)) {
        return 0;
    } else if (this.next == null) {
        return null;
    } else {
        return 1 + this.next.indexOf(value);
    }
}
}

MyLinkedListTester 类

package linkedlist;

public class MyLinkedListTester {
    public static void main(String[] args) {
        MyLinkedList myLinkedList = new MyLinkedList();
        myLinkedList.add(1);
        myLinkedList.add(2);
        myLinkedList.add(3);
        myLinkedList.add(4);

        System.out.println("Index Of Array: " + myLinkedList.indexOf(3));
        MyLinkedList linkedList = myLinkedList.remove(3);
    }
}

【问题讨论】:

  • 啊,这样比较好。对我来说,第一个想法是创建另一个方法private remove(MyLinkedList previous, int index),它是从remove(int index) 方法调用的。然后可以递归地使用该方法。我不会使用Integer,除非确实需要(可为空!)对象引用。当然也可以创建双链表,但也可能超出范围。
  • 感谢您递归删除的想法。但是,在您的情况下,迭代方法是最简单和最有效的选择。

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


【解决方案1】:

如 cmets 中所述,迭代方法在大多数情况下更容易且更有效。无论如何,我认为你这样做是一种练习,因为在 Java 中你已经有一个 LinkedList。

所以首先你的想法有一种错误(据我所知)。这也是一种糟糕的设计选择。您创建您的MyLinkedList 并将数据直接保存到其中,下一个也是MyLinkedList 类,但它不是列表,而是Node。应该只有一个列表和 0 - 许多节点。

例如,我不知道如何执行删除函数,该函数将返回已删除的 Node(在您的情况下为 MyLinkedList),并且还让您保留列表以防您删除第一个元素列表。

如果您正在查看实现,这就是他们使用节点的原因,而且它也更合乎逻辑(列表不包含“列表元素”)等等......

其他说明:如果您尝试获取不存在的元素(1 + null => 错误),您的 indexOf 函数将返回错误。

无论如何。你要做的是创建一个Node。 (顺便说一句,如果你真的想要一个真正的 LinkedList,你可以使用泛型而不是 int/Integer)。

下面我将发布我的解决方案如何做到这一点(可能会更好,但我就是这样做的)。我还编写了一个 toString 方法来查看 List 的外观(据我所知,它的工作原理)。如果您想在没有节点的情况下仍然使用您的代码,它应该让您了解如何使用 remove 解决您的问题。您也可以将一些逻辑放入 Node 类中,但对我而言,Node 只是一个容器,并不真正包含任何逻辑。

public class MyLinkedList {
    private Node head;

    public MyLinkedList() {
    }

    public class Node{
        private int value;
        private Node next = null;

        public Node(int value){
            this.value = value;
        }

        public int getValue(){
            return value;
        }

        public Node getNext(){
            return next;
        }

        public void setNext(Node next){
            this.next = next;
        }

    }

    public void add(int value) {
        Node next = new Node(value);
        if(head == null){
            head = next;
        } else {
            addRecursive(head,next);
        }
    }

    private void addRecursive(Node node, Node next) {
        if(node.next == null){
            node.setNext(next);
        } else {
            addRecursive(node.getNext(),next);
        }
    }

    public Node remove(int index){
        Node removeNode = head;
        if(index == 0){
            head = head.getNext();
        } else {
            removeNode = removeRecursive(head,index-1);
        }
        return removeNode;
    }

    private Node removeRecursive(Node node, int index){
        Node removeNode = node.getNext();
        if(index == 0){
            node.setNext(removeNode.getNext());
        } else {
            removeNode = removeRecursive(node.getNext(),index-1);
        }
        return removeNode;
    }

    public int indexOf(int value) {
        if (head == null){
            return -1;
        }  else if (head.getValue() == value){
            return 0;
        } else {
            return indexOfRecursive(head,value,0);
        }
    }

    private int indexOfRecursive(Node node, int value, int index) {
        if(node.getNext() == null){
            return -1;
        } else if(node.getNext().getValue() == value){
            return index + 1;
        } else {
            return indexOfRecursive(node.getNext(),value,index+1);
        }
    }

    @Override
    public String toString(){
        if(head == null){
            return "";
        } else {
            return toStringRecursive(head,"["+head.getValue());
        }
    }

    private String toStringRecursive(Node node, String output){
        if(node.getNext() == null){
            return output + "]";
        } else {
            return toStringRecursive(node.getNext(),output + ", " + node.getNext().getValue());
        }
    }
}

【讨论】:

  • 感谢您的解释,我查看了 JDK 的 LinkedList 实现,因为它是我不太关心的迭代方法。关于你的回答,我会在空闲时间看看。我只是注意到在您的remove 方法中,如果headnullNullPointerException 将被提高。
  • @Badamchi 是的,我知道。当您删除 inbuild LinkedList 中不存在的元素时,您还将得到一个异常(IndexOutOfBoundsException),在我的情况下,我会让用户遇到 NullPointerException(也可以抛出 IndexOutOfBoundsException 或返回null / 处理不同)
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2012-03-04
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2010-09-19
  • 2023-04-03
相关资源
最近更新 更多