Java - 通过链接列表迭代无法正确排序

时间:2018-04-06 05:24:38

标签: java linked-list iterator nodes

我正在尝试迭代一个LinkedList(包含一个Object数据和一个Node的Nodes),并按照字母顺序排列的方式将元素添加到所述列表中。下面是这个addElement方法的代码片段,下面我将展示整个程序的输出,以及它出错的地方。

public void addElement(Object element) {
    LinkedListIterator iter = new LinkedListIterator();
    if (first == null) {
        addFirst(element); // If list is empty, make the input first
    } else {
        String input = String.valueOf(element);
        String current = String.valueOf(first.data);
        int compare = input.compareTo(current);
        while (iter.hasNext()) {
            if (compare > 0) { // element is greater than position
                // Do nothing, keep going
            } else if (compare < 0) { // element is where it needs to be
                // Since element is now smaller than the next thing,
                // break the loop to add it.
                break;
            } else { // element completely matches position
                // Do nothing, keep going
            }
            current = String.valueOf(iter.next());
            compare = input.compareTo(current);
        }
        iter.add(element);
    }
}

此输入,一次一个(没有空格或逗号),将是: 葡萄,甜瓜,苹果,桃子,香蕉

输出将是: (葡萄) (葡萄甜瓜) (苹果葡萄瓜) (Apple Grape Melon Peach) (Apple Grape Banana Melon Peach)

正如你所看到的,没有明显的理由(至少我可以看到),除了香蕉这个术语外,所有内容都按字典顺序排序。为什么它突然跳过Grape,一个元素领先于它应该是什么? Apple和Grape之间的任何单词都会出现这种情况,例如Cherry,所以我怀疑在第一个和第二个术语之间添加元素时存在逻辑错误。帮助将不胜感激,至于我的生活,我找不到逻辑错误。干杯!

3 个答案:

答案 0 :(得分:0)

在IDE中运行调试器,并检查要比较的inputcurrent的值。根据您的代码,input可能类似于java.lang.Object@61bbe9ba。这取决于元素的类是否正确覆盖了toString方法。如果是这种情况,则替换:

String input = String.valueOf(element);

使用:

String input = String.valueOf(element.data);

另一种可能性是data的{​​{1}}方法正在评估toString之类的内容。无论哪种方式,您都需要确保所比较的java.lang.Object@61bbe9bainput的值是正确的。

此外,更简单的排序方法是使用Collections提供的排序方法。下面是一个示例,其中compare是您的LinkedList,linkedList是您的LinkedList元素的类类型:

Element

另一种解决方案是使用相同的比较器创建TreeSet,遍历LinkedList并将每个元素添加到TreeSet。每次添加新元素时,TreeSet都会自动排序,并且比LinkedList具有更快的数据访问时间。 TreeSet为O(log n),而LinkedList为O(n)。

Collections.sort(linkedList, (Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));

答案 1 :(得分:0)

做得太多了,实际上一个人必须在一个位置之后插入,也在一个位置之前插入。

    String sought = String.valueOf(element);
    while (iter.hasNext()) {
        current = String.valueOf(iter.next());
        comparison = sought.compareTo(current);
        if (comparison == 0) {
            return; // Already added
        } else if (compare > 0) {
            // Sought element is larger than the current element,
            // so add it in front
            iter.previous();
            break;
        }
    }
    iter.add(element); // Add it after this one

答案 2 :(得分:0)

您的代码等同于以下简化版本:

public void addElement(Object element) {
    if (first == null) {
        addFirst(element); // If list is empty, make the input first
    } else {
        String input = String.valueOf(element);
        LinkedListIterator iter = new LinkedListIterator();
        String current = String.valueOf(first.data);
        while (iter.hasNext() && input.compareTo(current) >= 0) {
            current = String.valueOf(iter.next());
        }
        iter.add(element);
    }
}

现在,当您到达列表末尾或current大于input时,更容易看到循环退出。这样逻辑就可以了。

但现在看看你在比较input的内容!最初,您将其与data字段的字符串值进行比较。但是在循环中,您将它与iter.next()的字符串值进行比较,后者为您提供节点,而不是data的值。实际上,您将字符串"Banana""com.example.LinkedListNode@331fe1a"进行比较。您需要使用String.valueOf(iter.next().data)。 (假设您的LinkedListIterator按常规行事且iter.next()具有正确的返回类型。)

您可以通过更严格地处理数据类型来减少这些错误。具体来说,您应该考虑使LinkedList通用。也许你还没有开始研究泛型,但是当你这样做时,你会意识到他们如何使这个代码更整洁。

编辑:

如您所说iter.next()返回实际数据,那么问题必须在其他地方。你问题中循环的逻辑看起来没问题,所以我现在怀疑你LinkedListIterator类中的逻辑,特别是它的add方法。看起来它是在 next 元素之后而不是在当前元素之后添加。