【问题标题】:Creating a Generic Ordered Linked List in Java, trouble using compareTo()在 Java 中创建通用有序链表,使用 compareTo() 时遇到问题
【发布时间】:2012-08-07 23:24:06
【问题描述】:

[已解决]

我是一名 C++ 人员,正在为(希望)即将到来的工作学习 Java。因此,我正在自己练习在 Java 中实现链接列表。我完成了一个标准的双向链表,它工作得很好。然而,我随后尝试创建一个有序链表,并意识到无法重载 '

我在这个网站上查看了其他人的问题,但我仍然没有得到解决,所以我想我会发布我的代码并获得更适合我正在做的事情的答案。

以后..

链表类:

public class MyList<T>  {

/*** ~Public Interface~ ***/
       //insert, delete, size, print, etc.
       ...

    /*** Private Data Members ***/
       //node begin, end, T data
   ....


/** Private node class **/
//Represents the nodes in the list
private class node implements Comparable<T>{ //Don't know if this is right
    node next;
    node prev;
    T    data;

    node(node p, node n, T d){
        next = n;
        prev = p;
        data = d;
    }

    @Override
    public int compareTo(T o) {
        return (data <= o ? 1 : 0); //Get an error still here
    }

          /** Iterator **/
               //iterator class
}

有序链表类:

public class OrderedList<T> extends MyList<T> implements Comparable<T>{ //Pretty sure this is wrong

public void insert(T d){
    if(empty()){
        push_front(d);
    } else {
        MyList<T>.MyListIter it = begin();
        int i = 0;
             //This won't work obviously
        for(; i < size() || it.current().compareTo(it.next()) == -1; ++i, it.next()){
                    //find node to place the new node before it 
                        it.prev() //Need to go back one since we went forward in the loopcheck.


        }
    }
}

这里真的很茫然。如何实现类似于运算符重载的东西,以便我可以完成这个有序列表的实现?

我也在尝试掌握 Java 中的继承,所以如果您发现这方面有问题,也请随时提出意见。

谢谢大家。

更新:

好的,我进行了我认为必须进行的更改,但我仍然遇到错误。这是新代码:

MyList 类中的节点类:

private static class node<T> implements Comparable<T>{
    node<T> next;
    node<T> prev;
    T    data;

    node(node<T> p, node<T> n, T d){
        next = n;
        prev = p;
        data = d;
    }

    public int compareTo(T o) {
        return ((Comparable<T>) this.data).compareTo(o);
    }

}

有序列表:

公共类 OrderedList> 扩展 MyList{

compareTo 的用法:

if(((Comparable<T>) it).compareTo(it.next()) == -1) found = true;

编译器强迫我做这些转换,现在错误是:

MyList$MyListIter cannot be cast to java.lang.Comparable

列表迭代器类如下:

public class MyListIter{

它在 MyList 中。

编辑[已解决]

当我使用我的迭代器时,我没有使用 it.current() 来访问实际数据,而是使用 it.compareTo(..),但我的迭代器当然不是数据,因此不是对 compareTo() 有所了解。

【问题讨论】:

  • 你从不声明类型参数T;不过,您真正想要的是实现Comparable&lt;node&lt;T&gt;&gt;。由于您希望您的元素也是Comparable,因此您可能应该指定例如OrderedList&lt;T extends Comparable&lt;T&gt;&gt;;你不需要让OrderedList 实现Comparable 本身。
  • 另外,应该是Node&lt;T&gt;,而不是node
  • 您的一些代码被 HTML 破坏了,因为它前面有两个空格(在“有序列表:”标题下)。另外,您遇到了什么错误?

标签: java inheritance linked-list operator-overloading


【解决方案1】:

虽然这是一个很好的练习,但我不会雇用这样的人:a)更喜欢使用自己的 LinkedList 而不是内置的 b)当有排序集合时使用 LinkedList 作为排序集合,而 ArrayList 更有效对于这种.. ;)

我建议您阅读 LinkedList、ArrayList 和 TreeSet 的源代码,以了解它们是如何在 JDK 中实现的。我还建议您阅读java.lang.java.util. 中所有类和接口的源代码

您想让 Node 与其他节点具有可比性,并且您的数据类型也需要具有可比性。您还应该使用 Java 代码约定。

public class MyList<T extends Comparable<T>> {

static class Node {
    Node prev, next;
    T    data;

    Node(Node p, Node n, T d){
        next = n;
        prev = p;
        data = d;
    }
}

public void insert(T d){
    if(empty()){
        push_front(d);
        return;
    }
    for (Node<T> node = first;node.next != null; node = node.next) {
       // if less than we need to insert before.
       if (d.compareTo(node.data) < 0) {
          if (node == first) {
              first = new Node(null, first, d);
              node.prev = first;
          } else {
              node = new Node(node.prev, node, d);
              node.prev.next = node;
          }
          return;
       }

【讨论】:

  • 我实现它纯粹是为了学习。显然,我不会在工作中从头开始实现我自己该死的基本数据结构。您能否从概念的角度解释 > 。来自 C++,这完全没有意义。
  • 实际上实现单链表或双链表是一个常见的面试问题,所以这对面试来说并不是一个坏主意。我没有遇到过的排序链表。阅读 Java 源代码是学习棘手内容的最佳/最快方法之一。
  • &lt;T extends Comparable&lt;T&gt;&gt; 表示;我有一个类型T,它实现 Comparable,因此它可以与其他对象进行比较,它可以与其他T进行比较。
  • 除了需要使用compareTo 并且没有* 之外,您应该能够在C++ 中编写相同的代码。
  • 请注意,我更新了 OP 并添加了一些其他问题。再次感谢。
【解决方案2】:

正如您所说,您不能在 Java 中重载运算符。这意味着您的排序列表永远不能使用 。相反,您需要依靠数据对象来拥有compareTo() 方法,或者为列表的用户提供一种方法来提供Comparator 对象。如果您希望将列表严格限制为第一种情况,您可以将其声明为

public class OrderedList<T implements Comparable<T>> extends MyList<T>

这将保证插入到列表中的对象具有compareTo() 方法。现在您的 Node.compareTo() 函数只是将比较与此方法进行了比较:

public int compareTo(T o) {  
    return this.data.compareTo(o.data);
}

允许自定义Comparators 可能会有点棘手。我建议您在获得默认比较后将其保留。

附言您希望能够相互比较列表吗?如果是这样,那么让OrderedList 实现Comparable 是有道理的。但是,在您的列表类使用其基本操作之后,您可能希望将其留到以后的练习中。

【讨论】:

  • 谢谢,这很有帮助。我的迭代器和 compareTo() 现在有更多问题。 OP 已更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2013-11-06
  • 1970-01-01
  • 1970-01-01
  • 2020-12-12
  • 1970-01-01
  • 2013-10-04
  • 1970-01-01
相关资源
最近更新 更多