簡體   English   中英

Java - 遍歷鏈表無法正確排序

[英]Java - Iterating through a Linked List can't sort properly

我試圖遍歷 LinkedList(節點,包含一個對象數據和一個節點),並以字母順序排序的方式將元素添加到所述列表中。 下面是這個 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);
    }
}

一次輸入一個(沒有空格或逗號),將是:Grape、Melon、Apple、Peach、Banana

輸出將是:(葡萄)(葡萄瓜)(蘋果葡萄瓜)(蘋果葡萄瓜桃)(蘋果葡萄香蕉瓜桃)

正如您所看到的,沒有明顯的原因(至少我可以看到),除了術語 Banana 之外,所有內容都按字典順序排列得很好。 為什么它會突然跳過葡萄,比它應該在的位置提前一個元素? Apple 和 Grape 之間的任何單詞都會發生這種情況,例如 Cherry,因此我懷疑在第一項和第二項之間添加元素時存在邏輯錯誤。 幫助將不勝感激,至於我的生活,我找不到邏輯錯誤。 干杯!

在您的 IDE 中運行調試器並檢查正在比較的inputcurrent的值。 根據您的代碼, input可能類似於java.lang.Object@61bbe9ba 這取決於元素的類是否正確覆蓋了toString方法。 如果是這種情況,則更換:

String input = String.valueOf(element);

與:

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

另一種可能性是datatoString方法正在評估類似java.lang.Object@61bbe9ba東西。 無論哪種方式,您都需要確保被比較的inputcompare的值是正確的。

此外,一種更簡單的排序方法是使用 Collections 提供的排序方法。 這是一個示例,其中linkedList是您的 LinkedList,而Element是您的 LinkedList Element的類類型:

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

另一種解決方案是使用相同的比較器創建一個 TreeSet,遍歷 LinkedList 並將每個元素添加到 TreeSet。 每次添加新元素時,TreeSet 都會自動對其進行排序,並且具有比 LinkedList 更快的數據訪問時間的額外好處。 TreeSet 是 O(log n) 而 LinkedList 是 O(n)。

Set<Element> treeSet = new TreeSet<>((Element element1, Element element2) -> String.valueOf(element1.data).compareTo(String.valueOf(element2.data)));

做的太多了,事實上一個人必須在一個位置之后插入,在一個位置之前也插入。

    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

您的代碼等效於以下簡化版本:

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()的字符串值進行比較,它為您提供node ,而不是data的值。 所以你實際上是在比較字符串"Banana""com.example.LinkedListNode@331fe1a" 您需要使用String.valueOf(iter.next().data) (假設您的LinkedListIterator行為符合常規並且iter.next()具有正確的返回類型。)

您可以通過對數據類型更加嚴格來減少此類錯誤的發生。 具體來說,您應該考慮使您的LinkedList通用。 也許您還沒有開始學習泛型,但是當您開始學習時,您會意識到它們如何使代碼更簡潔。

編輯:

正如您所說的iter.next()返回實際數據,那么問題一定出在其他地方。 您問題中的循環邏輯看起來沒問題,所以我現在懷疑您的LinkedListIterator類內部的邏輯,特別是它的add方法。 看起來它是在下一個元素之后而不是在當前元素之后添加。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM