快速排序 - 不是一个稳定的排序

时间:2016-12-28 21:20:16

标签: sorting data-structures language-agnostic quicksort stable-sort

在排序

之后,稳定排序会讨论相同的键没有越过对方

在数组索引8处考虑重复键4& 9,按以下顺序,

  

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

     

分区逻辑说,

     

i指针从左向右移动。只要i值≤a[i],就移动a[pivot]swap(a[i], a[j])

     

j指针从右向左移动。只要j值≥≥a[j],就移动a[pivot]swap(a[i], a[j])

按照此程序两次,

  

a = [5 4 19 18 17 8 4 5 4 20]在i = 1& j = 9。

     

a = [5 4 19 18 17 8 4 5 4 20]停留在i = 2& j = 8

     

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

我的理解是,由于重复键4在两次交换后丢失了订单,因此快速排序不是稳定排序。

问题:

根据我的理解,这是快速排序不稳定的原因吗?如果是,我们是否有任何替代分区方法来维护上述示例中的密钥4的顺序?

1 个答案:

答案 0 :(得分:1)

Quicksort 本身的定义中没有任何内容可以使其稳定或不稳定。它可以是。

Quicksort在数组上最常见的实现涉及通过一对指针之间的交换进行分区,一个指针从头到尾进行,另一个从头到尾进行。这确实产生了一个不稳定的Quicksort。

虽然这种分区方法肯定很常见,但要求算法成为Quicksort。在将Quicksort应用于数组时,这只是一种简单而常见的方法。

另一方面,考虑在单链表上进行快速排序。在这种情况下,您通常通过创建两个单独的链接列表来进行分区,一个包含小于枢轴值的链接列表,另一个包含大于枢轴值的链接列表。因为你总是从头到尾遍历列表(没有很多其他合理的选择与单链表)。只要将每个元素添加到子列表的 end ,您创建的子列表就会按原始顺序包含相同的键。因此,结果是稳定的排序。另一方面,如果您不关心稳定性,可以将元素拼接到子列表的开头(稍微容易做到复杂度不变)。在这种情况下,排序将(再次)不稳定。

分区链表的实际机制非常简单,只要你不太喜欢选择分区。

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;