Reputation: 3787
I would like to implement selection sort using LinkedList in Java.
I know how to do it with ArrayList, please don't comment that I should use it instead. I am interested in demonstrating the advantages (fast insertion and removal) and disadvantages of linked lists compared to arrays.
I know how to do this in C where I have pointers and access to the list's node struct. But in Java the closest thing I found is the ListIterator.
Here is my code that compiles and works:
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 );
}
}
My problems are the following:
A) To iterate from 1 beyond the position of the outer iterator (it), I have to call listIterator with and index. I suspect that this method walks from the beginning of the list to the given position. This is wasteful because we already have an iterator to an element before. How can I efficiently iterate from a given iterator until the end of the list?
B) To swap elements, I have to use list.set with and index which causes the same inefficiency as A).
C) I planned to swap the elements by modifying the list nodes, not just their value. As I understand my current code leads to the middle of the below diagram, while I wanted to get to the bottom part:
In the current algorithm this may make no difference but I would like to examine other sorting algorithms, and this LinkedList does not work as I expected.
A one-on-one swapping is not the same as removing an element and inserting it before another. Example: abcdefgh is the original, swapping b and f leads to afcdebgh, while removing and inserting f before b would result in afbcdegh. I thought LinkedLists can perform the latter efficiently. If I can use them only like Arrays, then why do LinkedLists exist at all?
Upvotes: 0
Views: 230
Reputation: 103273
I am interested in demonstrating the advantages (fast insertion and removal) and disadvantages of linked lists compared to arrays.
Congratulations!! You have succeeded in showing the disadvantages of java's particular implementation of LinkedLists. They suck, don't use them - their performance is worse than big-O notation suggests (modern CPU architecture and linked lists just don't like each other), and actually trying to use the advantages is impossible without bending over backwards and using ListIterator
. However, ListIterator's API is not sufficient to do stuff like swapping elements, because you don't get direct access to the tracker nodes (the nodes containing the prev, next, and value fields).
then why do LinkedLists exist at all?
They probably shouldn't exist in the first place. "Why do they?" is tantamount to asking: "What was the core java dev team thinking somewhere in the 90s, when this stuff was written?"
We can guess.
arraylist.add()
call takes a ton of time, relatively speaking. These days that's completely irrelevant; if you want to write an app that never gets that kind of sudden slowdown, the JVM is not what you want (garbage collection pauses, OSes that pause, etc), so the 'benefit' is irrelevant. But it was (deemed to be) relevant way back then in the 90s when it was written. People would definitely expect an impl and would file feature requests for it, even if the core team did realize it was probably rarely a good idea to actually use them.Upvotes: 1