【问题标题】:java - inserting/removing into a sorted list recursiveyjava - 递归插入/删除到排序列表
【发布时间】:2016-10-10 15:59:40
【问题描述】:

我正在实现这个抽象类,其中实现的所有功能都必须使用递归来完成:

public abstract class List<E> implements Iterable<E> {
protected class Node<T> {

    protected Node(T data) {
        this.data = data;
    }

    protected T data;
    protected Node<T> next;
}

public abstract void insert(E data);
public abstract void remove(E data);
public abstract E retrieve(int index);
public abstract boolean search(E data);

protected Node<E> head;
}

以下是我目前的实现。我相信我已经正确地完成了搜索和检索方法,并且大多数删除方法都正确。我担心的一个问题是我对插入方法的错误(我并不特别需要工作代码,但可能是一个伪代码,比如当抽象类只接受一个数据参数时你将如何插入的解释,导致需要一个私有类)。另一个问题是 remove 方法的这种情况:

if (key.compareTo(temp.data) == 0){

        }

我不确定我应该如何删除头节点,因为只能访问当前节点和下一个节点。任何帮助将不胜感激!

import java.util.Iterator;
import java.util.Random;

public class SortedList<E extends Comparable<? super E>> extends List<E> {

public static void main(String[] args) {

    Random rand = new Random(1);
    SortedList<Integer> list = new SortedList<Integer>();

    list.insert(1);
    System.out.println(list.search(1));
}
 public Iterator<E> iterator() {

        return new Iterator<E>() {
            public boolean hasNext() {
                return curr != null;
            }
            public E next() {
                E temp = curr.data;
                curr = curr.next;
                return temp;
            }
            public void remove() {
                throw new UnsupportedOperationException();
            }
            private Node<E> curr = (Node<E>)head;
        };
    }


public void insert(E data) {
    Node<E> temp = new Node<E>(data);
    Node<E> curr = head;
     if (head == null || data.compareTo(head.data) < 0) {
            temp.next = head;
            head = temp;
        }
    insert(curr, data);
}
    private void insert(Node<E> curr, E data){
        if (curr.next == null) {
            curr.next.data = data;
        } else {
            curr.next.insert(curr, data);
        }
    }


public void remove(E data) {
    Node<E> curr = head;
    remove(curr, data);
}
    private void remove(Node<E> temp, E key){
        if (temp == null){
            return;
        }
        if (key.compareTo(temp.data) == 0){

        }
        if (key.compareTo(temp.next.data) == 0){
            temp.next = temp.next.next;
            return;
        }
        if (key.compareTo(temp.next.data) < 0){
            remove(temp.next, key);
        }

    }




public E retrieve(int index) 
{
    Node<E> curr = head;
    int counter = 0;
    return retrieve(curr, index, counter);
}
 private E retrieve(Node<E> temp, int idx, int c)
   {
      if (idx == c){
          return temp.data;
      }
      return retrieve(temp.next, idx, c++);
   }


 public boolean search(E data)
   {
     Node<E> curr = head;
     return search(curr, data);
   }
   private boolean search(Node<E> temp, E key)
   {
      if (temp == null){
         return false;
      }
      if (key.compareTo(temp.data) == 0){
        return true;
      }
      if (key.compareTo(temp.data) < 0){
         return search(temp.next, key);
      }
      return false;
   }

}

【问题讨论】:

    标签: java recursion sortedlist


    【解决方案1】:

    从头部移除:

    既然您知道您的列表应该始终进行排序,如果您删除(当前)头部值,那么下一个头部应该是行中的“下一个”。您最初只能访问“头”节点,并且必须逐个向下移动列表。

    因此,在这种情况下,假设您有一群人按照名字的顺序排队等候。如果他们都牵手并按顺序与下一个人形成链条,然后您将排在第一排的第一个人移走。您可以从逻辑上假设握着他们手的人是新的负责人。

    Node<E> temp = new Node<E>(data);
    if(check to see if you want to remove head){
         temp.next = head.next; //current head points to next in line so so shall new head(temp);
         head = temp; //head ref variable points to only new head and old one is inaccessible and will be cleared out during garbage collection. 
    }
    

    中间插入和取出:

    使用前面牵手的类比。如果我需要在两个人中间“插入”一个人,我首先必须找到他们所属的位置,然后让他们与“当前”和“下一个”之前和之后的人联系。

    对于您的插入代码,您必须搜索直到找到正确的插入位置,该位置可以在两个节点之间,而不是假设如果下一个值为空,您将只插入。

    private void insert(Node<E> curr, E data){
        if (curr.next == null) {
            curr.next.data = data; //only inserts if next value is null
        } else { // what about inserting 3, into a list of {1,5}. 
            curr.next.insert(curr, data);
        }
    }
    

    您需要检查当前值和下一个值在排序顺序中是否正确。

    else if(curr.data <= data && curr.next.data > data){
            // you've found the nodes you want to insert in between
    }else{
      ... keep searching until you hit a null
    }
    

    【讨论】:

    • 伪代码将不胜感激插入。对于你提到的删除条件,我确实理解这个逻辑,但我的问题是这个 sortedlist 类实现,没有前一个节点,我们“删除”节点的方式是将 node.next 设置为 node.next 。下一个。在这种情况下,没有指向头节点的“.next”,这是我迷路的地方。
    • 使用当前节点,您可以检查任意数量的节点,只要您知道通过链接“next”来检查多少个节点。我可以检查 curr.next.next。如果我想要 3 下线。如果明智地使用临时节点并向下检查,则不需要“上一个”节点。
    • @abdi 为什么需要一个指向头部的下一个节点?如果您需要在头部插入,那么只需将 Node ref 节点设置为您的新节点,我相信您目前做得正确。要删除 head,您只需指向 temp.next = head.next。然后头=温度。无法访问这个旧的 head 值,它将被 gc 清除。
    • 我相信我现在已经正确地完成了插入方法,但是当尝试使用我在原始帖子中放置的 main 方法运行程序(它编译得很好)时,它给了我一个空指针异常:gyazo.com/49cf251d5c7d70872513949ae12760d1这不是处理了我插入的第一个条件吗?
    • 这是因为您在 curr 为空时调用了 insert。如果头节点为空,则会发生这种情况。你做的,curr = head; (如果列表为空,则为 null)。然后,虽然你设置了新的 head,但你没有修复 curr 并执行 insert(curr,data)。您需要将 insert(curr,data) 作为 else 语句。
    猜你喜欢
    • 2012-02-29
    • 2012-11-17
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多