[英]Selection sort with LinkedList in Java
我想在 Java 中使用 LinkedList 實現選擇排序。
我知道如何用 ArrayList 做到這一點,請不要評論我應該改用它。 我有興趣展示鏈表與 arrays 相比的優點(快速插入和刪除)和缺點。
我知道如何在 C 中執行此操作,在那里我有指針並可以訪問列表的節點結構。 但在 Java 中,我發現最接近的是 ListIterator。
這是我編譯和工作的代碼:
class Pile {
private final List< Card > cards;
public void sortWithSelectionSortUsingLinkedList( final Comparator< Card > comparator ) {
final List< Card > list = new LinkedList< Card >( cards );
cards.clear();
for( final ListIterator< Card > it = list.listIterator(); it.hasNext(); ) {
final int currentIndex = it.nextIndex();
final Card currentCard = it.next();
int indexToMoveToCurrent = currentIndex;
Card cardToMoveToCurrent = currentCard;
for( final ListIterator< Card > jt = list.listIterator( it.nextIndex() ); jt.hasNext(); ) { // Problem A
int indexPossiblyLower = jt.nextIndex();
Card cardPossiblyLower = jt.next();
if( comparator.compare( cardPossiblyLower, cardToMoveToCurrent ) < 0 ) {
cardToMoveToCurrent = cardPossiblyLower;
indexToMoveToCurrent = indexPossiblyLower;
}
}
it.set( cardToMoveToCurrent );
list.set( indexToMoveToCurrent, currentCard ); // Problem B
// The below swapping code causes ConcurrentModificationException // Problem C
// it.previous();
// it.add( list.remove( indexToMoveToCurrent ) );
}
cards.addAll( list );
}
}
我的問題如下:
A) 要從 1 迭代到外部迭代器 (it) 的 position 之外,我必須調用帶有索引的 listIterator。 我懷疑此方法從列表的開頭走到給定的 position。這很浪費,因為我們之前已經有一個元素的迭代器。 我怎樣才能有效地從給定的迭代器迭代到列表的末尾?
B) 要交換元素,我必須使用 list.set 和索引,這會導致與 A) 相同的低效率。
C) 我計划通過修改列表節點來交換元素,而不僅僅是它們的值。 據我了解,我當前的代碼指向下圖的中間部分,而我想到達底部:
在當前的算法中,這可能沒有什么區別,但我想檢查其他排序算法,而這個 LinkedList 並不像我預期的那樣工作。
一對一的交換與刪除元素並將其插入到另一個元素之前不同。 示例:abcdefgh 是原始的,交換 b 和 f 導致 afcdebgh,而在 b 之前刪除和插入 f 將導致 afbcdegh。 我認為 LinkedLists 可以有效地執行后者。 如果我只能像 Arrays 那樣使用它們,那么為什么 LinkedLists 存在呢?
我有興趣展示鏈表與 arrays 相比的優點(快速插入和刪除)和缺點。
恭喜你,你已經成功地展示了 java 的特定 LinkedLists 實現的缺點,它們很爛,不要使用它們 - 它們的性能比 big-O 符號所建議的更差(現代 CPU 架構和鏈表只是彼此不喜歡),如果不向后彎腰並使用ListIterator
,實際上不可能嘗試利用這些優勢。 但是,ListIterator 的 API 不足以執行交換元素之類的操作,因為您不能直接訪問跟蹤器節點(包含上一個、下一個和值字段的節點)。
那為什么 LinkedLists 存在呢?
它們可能一開始就不應該存在。 “他們為什么這樣做?” 無異於問:“核心 java 開發團隊在 90 年代某處思考什么,當這些東西被寫出來的時候?”
我們可以猜測。
arraylist.add()
調用經常需要花費大量時間。 如今,這完全無關緊要了; 如果您想編寫一個永遠不會突然變慢的應用程序,那么 JVM 不是您想要的(垃圾收集暫停、操作系統暫停等),因此“好處”是無關緊要的。 但它在 90 年代編寫時(被認為是)相關的方式。 人們肯定會期待一個 impl 並為其提交功能請求,即使核心團隊確實意識到實際使用它們可能很少是一個好主意。
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.