【问题标题】:How to manually implement a Linked List in Java without using a Constructor?如何在不使用构造函数的情况下在 Java 中手动实现链表?
【发布时间】:2015-10-03 20:31:40
【问题描述】:

我意识到已经存在一些很好的线程来讨论如何在 Java 中实现链表,但是我似乎找不到一个不使用这样的构造函数的线程,

public LinkList() {
    Link = null;
}

或类似的东西。但是,我没有在我的代码中这样做,因此我在编写一些方法时遇到了麻烦。

我有一个名为 Link 的类,其中包含以下代码,注意没有像上面显示的那样的任何构造函数:

public class Link {
private Link next = null;
private String value = null;

public Link getNext(){
    return next;
}

public void setNext(Link nextLink){
    next = nextLink;
}

public String getValue(){
    return value;
}

public void setValue(String aValue){
    value = aValue;
}
}

然后我有我的LinkedList 类,其中包含以下代码:

public class LinkedList {
private Link head = null;
private Link tail = null;

public Link getHead(){
    return head;
}

public void setHead(Link aLink){
    head = aLink;
}

public Link getTail(){
    return tail;
}

public void setTail(Link aLink){
    tail = aLink;
}

public boolean isEmpty(){
    return(head == null && tail == null);
}

public void addLast(String aString){
    Link link = new Link();
    link.setValue(aString);
    //tail.setNext(link);
    if(isEmpty()){
        head = link;
    }else{
        tail.setNext(link);
    }
    tail = link;

    }

public void addFirst(String aString) {
    Link link = new Link();
    link.setValue(aString);

    if(isEmpty()){  
        tail = link;
    }else{
        head.setNext(link);
    }
    head = link;        
}

public Link removeFirst(){
    Link temp = head;
    head = temp.getNext();
    temp.setNext(null);

    return temp;
}

}

我的addFirst 方法和我的isEmpty 方法似乎都有效,但我的addLastremoveFirst 方法却不行。我画了图片,查看了伪代码,并在互联网上搜索,但我似乎无法弄清楚这一点。

我需要知道如何让我的 addLastremoveFirst 方法正常工作,而不必像我一直看到的所有其他示例代码一样在开头添加构造函数。

这是他们需要通过的测试:

    @Test
public void testRemoveFirst(){
    list.addFirst("three");
    list.addFirst("two");
    list.addFirst("one");
    assertTrue("one".equals(list.removeFirst()));
    assertTrue("two".equals(list.removeFirst()));
    assertTrue("three".equals(list.removeFirst()));
}

@Test
public void testAddLast(){
    list.addFirst("three");
    list.addFirst("two");
    list.addFirst("one");
    assertTrue( "three".equals(list.removeLast()));
    assertTrue( "two".equals(list.removeLast()));
    assertTrue( "one".equals(list.removeLast()));
    assertNull(list.removeLast());
}

【问题讨论】:

  • 为什么不想要构造函数?
  • 你能提供一个那些方法不起作用的测试用例吗?
  • (为什么你认为构造函数和你的问题有关系?)
  • 你在两个类中都有一个构造函数,你自己在这里使用Link link = new Link();编译器会为你生成它。
  • "...我的教授希望我们知道如何在不使用链接列表的情况下创建链接列表。" - 啊哈。你正在学习那些应该被命名为“愚蠢的 Java 技巧”的课程。

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


【解决方案1】:

需要对您的代码进行一个更改:您希望新链接指向您的旧头作为“下一个”(而不是相反),因为您想在开头插入它。

public void addFirst(String aString) {
        Link link = new Link();
        link.setValue(aString);

        if (isEmpty()) {
            tail = link;
        } else {
            link.setNext(head);
        }
        head = link;
    }

此外,您需要更改测试,因为现在您将 String 与 Link 实例进行比较,而不是 String 与 String

    assertTrue("one".equals(list.removeFirst().getValue()));
    assertTrue("two".equals(list.removeFirst().getValue()));
    assertTrue("three".equals(list.removeFirst().getValue()));

在这些更改之后,我的测试通过了(第一个,您没有为第二个实现 removeLast 方法)。

【讨论】:

  • 哦,好的。第一部分是有道理的,我改变了你说的测试和绿灯。但是,我想知道是否有办法让它按照它的编写方式变成绿灯?我的教授是写测试的人,但我认为他说了一些话,就像他写错了其中一个一样。但是,我不确定。
  • 如果您的 list.removeFirst() 方法将返回 String 而不是 Link,您可以让它们通过。您实际上应该以这种方式实现它,因为您的List 实现的用户不应该知道实现细节。 Link 类是一个实现细节,只能在内部使用,而不能在外部可见(甚至可以通过使其成为 List 的内部静态类或使其包在与 List 类相同的包中成为私有包来强制执行)。此外,您在add 方法中从用户那里获取String 实例,在removeFirst 中返回String 是一致的。
  • 我对如何写这个感到困惑。将其更改为 String 类型,并让它返回一个字符串,但是如何?花了这么多时间,我的大脑感觉如此煎熬。
  • 您只需将removeFirst方法的最后一行从return temp;更改为return temp.getValue();,并将方法签名更改为返回String。我认为没有其他需要更改的地方。
  • addLast 在我看来相当不错。 remove last 并不是removeFirst 的简单逆,因为你有一个单链表。您有对tail 链接的引用,但您不知道tail 链接之前的内容。因此,当您想要删除您的尾部时,您需要将“尾部之前的内容”的指针更改为null,但除了迭代列表直到找到它之前,您无法以任何其他方式找到它。您可以在 google 中找到一些示例,例如 stackoverflow.com/questions/15792682/…
【解决方案2】:

您不需要构造函数将null0false 分配给对象字段。字段自动获取这些值。只需删除仅执行此类分配的构造函数,执行时不会有任何区别。

您还可以在声明中直接指定其他默认值,例如int a = 17,还可以包含int b = a + 1 等表达式,前提是之前已经声明了字段a。但是您不能为不同的实例传递必须具有不同值的参数。这就是构造函数的用途。

您可能还存在其他错误,但这不是构造函数的责任。

大多数情况下,开发人员只是使用现成的解决方案LinkedList

【讨论】:

  • 我知道此信息。我想我对我想问的问题有点困惑。我只是不知道该去哪里/如何编写和传递这两种方法。
  • 为什么要问你是否知道?
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-01-05
  • 2015-10-19
  • 2017-05-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多