QuickSort on Doubly Linked List
Asked Answered
D

3

2

I want to implement the QuickSort Algorithm on a sync Doubly Linked List. I give the function "partition" the left and right border, then it starts to search lower values on the left side and put the greater ones on the right side. This works because my pivot Element is alway the most rightern one and after this steps it is in the middle.

I always get an endless loop and I dont know why? Maybe wrong abort condition?

Her my code:

private void quickSortRec(DoublyLinkedList in, ListElement l, ListElement r) {

    ListElement pivot = partition(in, l, r);



    if(pivot!=null && l!=r){
        quickSortRec(in, in.first, pivot.prev);
        quickSortRec(in, pivot.next, in.first.prev);
    }
}


public ListElement partition(DoublyLinkedList in, ListElement l, ListElement r){


    ListElement pivot = r;
    ListElement walker = l;


    if(l!=r){


        while(walker != pivot){

            if(walker.getKey() >= pivot.getKey()){

                System.out.println(walker.getKey());

                if(walker.prev == r){
                    l = walker.next;
                    r = walker;
                }
                else{


                    ListElement h1 = walker.prev;
                    ListElement h2 = walker.next;

                    h1.next = h2;
                    h2.prev = h1;
                    walker.prev = pivot;
                    walker.next = l;
                    pivot.next = walker;
                    l.prev = walker;
                    r = walker;

                }

            }
            walker = walker.next;
        }

        if(l.prev == r)
            in.first = l;

        ListElement p = in.first;
        do{
            System.out.print(p.toString()+" ");
            p = p.next;
        }while(p != in.first);

        System.out.println();



        return pivot;

    }

    return null;
}


}
Detrude answered 30/4, 2013 at 14:48 Comment(2)
What is your question?Garceau
Oh I am sorry :) I always get an endless loop and I dont know why? Maybe wrong abort condition?Detrude
P
1

Just from a quick skim, it seems that your list is not only doubly linked, but also is connected at the ends (so it's more like a Ring than like a list). In other words, if I were to iterate over your list (containing elements A, B, C, D), it wouldn't be:

A -> B -> C -> D -> stop

Instead it would be

A -> B -> C -> D -> A -> B -> C -> D -> A -> B ..... etc.

I suspect that could be why you are having an infinite loop.

I would create a reference to the last element of your list in your DoublyLinkedList class (example: in.last), use that for getting the last element, and have the first and last elements link to either null or some sort of NullListElement extends ListElement


If you must keep it as a ring, I will still add a reference to the last element of your list, so that you can say something like:

if(walker == in.last) break; // stop
Pseudoscope answered 30/4, 2013 at 15:7 Comment(4)
Yeah but I want t make it for a "ring". I also wrote that it is a SYNC Doubly Linked List... I thougth that "sync" mean this.Detrude
If it's a ring, sorting is kind of meaningless right? Because after the biggest element is the smallest element again. (By the way I've never heard sync used to mean that)Pseudoscope
Yeah sure, but its a school project so I have to do it... And we have a mark for the list, where it begins if you mean that.Detrude
@Detrude I think it is not "sync" but it's "cyclic".Dome
M
1
Node partition(Node start, Node end){
    Node l = start;
    Node h = end.previous;
    Node pivot = end;

    if(end!=null && end.next!=start){ //Whenever deal with end.next, check null check
        while(h!=null && h.next!=l){//Whenever deal with end.next, check null check
            System.out.println("gumi");
            if(l.data<pivot.data)
                l=l.next;
            else if(h.data>pivot.data)
                h=h.previous;
            else{
                int temp = l.data;
                l.data = h.data;
                h.data = temp;
            }   
        }   
        int temp = pivot.data;
        pivot.data = l.data;
        l.data = temp;
    }
    return l;

}
void quicksort(Node start, Node end){
     System.out.println("jose");
   if(end!=null && end.next!=start ){ //Whenever deal with end.next, check null check , end should not be less than start: so the condition end.next!=start 
       System.out.println("Quixk");
       Node pivot = partition(start,end);
       quicksort(start, pivot.previous);
       quicksort(pivot.next, end);
   }

}
Mustache answered 13/3, 2017 at 6:32 Comment(0)
C
0

Here is an implementation for QuickSort using a DoublyLinkedList class which contains a reference to the first (in.first) ListElement, a list element contains a key and prev and next references:

public DoublyLinkedList quicksort(DoublyLinkedList in, int numOfElements) {
    in.first = partition(in.first, in.first.prev);
    return in;
}

private ListElement partition(ListElement first, ListElement pivotElement) {
    ListElement left = first;
    ListElement right = pivotElement;

    while (left != pivotElement) {
        if (left.getKey() > pivotElement.getKey()) {
            ListElement next = left.next;
            if (left == first)
                first = next;
            //Remove currentLeft
            left.prev.next = left.next;
            left.next.prev = left.prev;

            //Connect with element after currentRight
            left.next = right.next;
            right.next.prev = left;

            //Connect with pivotElement
            left.prev = right;
            right.next = left;

            right = left; //Switch right with left, since we just swapped their positions
            left = next;  //Assign left to the next object (from the left part)
        } else {
            left = left.next;
        }
    }
    if (first != pivotElement.prev && first != pivotElement)
        first = partition(first, pivotElement.prev);
    if (pivotElement != right)
        partition(pivotElement.next, right);
    return first;
}

At the time of this writing, when I run this on my desktop computer with a very recent Haswel CPU I get the following results:

Quicksort:
1.000.000 Items: 696ms
8.300.000 Items: 8131ms

Note that this is much slower than my MergeSort implementation for the same data structure, for which I get the following timings on the same computer with the same input:

Mergesort:
1.000.000 Items: 466ms
8.300.000 Items: 5144ms

Note the timings are specific to my hardware and you might get different results.

Chewy answered 10/1, 2014 at 20:36 Comment(0)

© 2022 - 2024 — McMap. All rights reserved.