1

Stable sort talks about equal keys NOT getting past each other, after sorting

Consider duplicate key 4 at array index 8 & 9, in the below sequence,

a = [5 20 19 18 17 8 4 5 4 4] where pivot = 0, i = 1, j = 9

Partition logic says,

i pointer moves left to right. Move i as long as a[i] value is ≤ to a[pivot]. swap(a[i], a[j])

j pointer moves right to left. Move j as long as a[j] value is ≥ to a[pivot]. swap(a[i], a[j])

After following this procedure two times,

a = [5 4 19 18 17 8 4 5 4 20] Swap done at i = 1 & j = 9.

a = [5 4 19 18 17 8 4 5 4 20] Stops at i = 2 & j = 8

a = [5 4 4 18 17 8 4 5 19 20] Swap done at i = 2 & j = 8

My understanding is, as duplicate key 4 lost their order after two swaps, Quick sort is not stable sort.

Question:

As per my understanding, Is this the reason for Quick sort not being stable? If yes, Do we have any alternative partition approach to maintain the order of key 4 in the above example?

Community
  • 1
  • 1
overexchange
  • 15,768
  • 30
  • 152
  • 347
  • 1
    Quick sort is not a stable sort — that is for sure. There are ways to make a quick sort stable; they involve recording somehow the original order of the rows so that when two elements compare equal ignoring the original position, you can tell which order the two should be in the output by using the original position information. How you do that in detail is a trickier discussion. You can probably find something online with a search such as 'stable quicksort'. – Jonathan Leffler Dec 28 '16 at 23:19
  • @JonathanLeffler tried to make stable sort [here](http://stackoverflow.com/questions/41715443/can-quick-sort-become-stable-sort), but failed – overexchange Jan 18 '17 at 09:37
  • Have you looked at the other questions on SO found by searching for 'stable quicksort'? There are quite a lot of them; at least some will have good answers. You also seem to have been given a very respectable answer in that question (SO 4171-5443). – Jonathan Leffler Jan 18 '17 at 20:25

1 Answers1

1

There's nothing in the definition of Quicksort per se that makes it either stable or unstable. It can be either.

The most common implementation of Quicksort on arrays involves partitioning via swaps between a pair of pointers, one progressing from end to beginning and the other from beginning to end. This does produce an unstable Quicksort.

While this method of partitioning is certainly common, it's not a requirement for the algorithm to be a Quicksort. It's just a method that's simple and common when applying Quicksort to an array.

On the other hand, consider doing a quicksort on a singly linked list. In this case, you typically do the partitioning by creating two separate linked lists, one containing those smaller than the pivot value, the other containing those larger than the pivot value. Since you always traverse the list from beginning to end (not many other reasonable choices with a singly linked list). As long as you add each element to the end of the sub-list, the sub-lists you create contain equal keys in their original order. Thus, the result is a stable sort. On the other hand, if you don't care about stability, you can splice elements to the beginnings of the sub-lists (slightly easy to do with constant complexity). in this case, the sort will (again) be unstable.

The actual mechanics of partitioning a linked list are pretty trivial, as long as you don't get too fancy in choosing the partition.

node *list1 = dummy_node1;
node *add1 = list1;
node *list2 = dummy_node2;
node *add2 = list2;

T pivot = input->data; // easiest pivot value to choose

for (node *current = input; current != nullptr; current = current->next)
    if (current->data < pivot) {
        add1->next = current;
        add1 = add1 -> next;
    }
    else {
        add2->next = current;
        add2 = add2->next;
    }
add1->next = nullptr;
add2->next = nullptr;
Jerry Coffin
  • 476,176
  • 80
  • 629
  • 1,111
  • How would u select the pivot element using linked list? O(k)? Can u imagine better performance using linked list? Merge/quick sort are famous for performance unlike element art sorts – overexchange Jan 17 '17 at 11:21
  • Yes, I can imagine situations where a linked list would give better performance than an array. No, it's not particularly common--but the question here was about characteristics of Quicksort, not the circumstances under which using a linked list would be justified (if it had been, I'd have voted to close it as a dupe of [this earlier question](http://stackoverflow.com/q/2429217/179910)). I'm not quite sure what you mean by "element art sorts" so I can't comment meaningfully on that. – Jerry Coffin Jan 17 '17 at 14:46
  • Can you help me understanding, what is your way of partitioning using linked list? that will help provide stable sort – overexchange Jan 18 '17 at 07:23
  • @overexchange: I've added some C-like pseudo-code for partitioning a linked list. – Jerry Coffin Jan 18 '17 at 07:39
  • I tell you what, It is impossible to maintain stable sort, either using array or linked list, by maintaining `j` as `mid` instead of `listSize-1` – overexchange Jan 18 '17 at 09:12
  • @overexchange: I think that statement needs some context before it's meaningful. `j`, by itself, doesn't mean anything to me. – Jerry Coffin Jan 18 '17 at 15:00