Why does a quick sort code break stability?

Below is the logic partition()used qSort(),

static void qSort(List *list, int low, int high, compareTo compare){

  if(high <= low){
    return; // no partition for sub array of size 1
  }
  int pivotIndex = partition(list, low, high, compare);
  qSort(list, low, pivotIndex-1, compare);
  qSort(list, pivotIndex+1, high, compare);
}

static int partition(List *list, int low, int high, compareTo compare){

  int pivot = low;
  int leftIndex = low + 1;
  int rightIndex = high;
  const void **array = list->array;

  while(true){

    while( leftIndex < high  && (compare(array[leftIndex], array[pivot]) < 0) ){
      leftIndex++;
    } 

    while( rightIndex > pivot && (compare(array[rightIndex], array[pivot])  >  0) ){
      rightIndex--;
    }

    if(leftIndex >= rightIndex){
      break;               // partition is done
    }
    if( compare(array[leftIndex], array[rightIndex]) == 0 ){
      leftIndex++; rightIndex--;
      continue;                   //Maintain stability
    }
    arraySwap(list, leftIndex, rightIndex);
  }
  if( compare(array[pivot], array[rightIndex]) != 0 ){
    arraySwap(list, pivot, rightIndex);           // Maintain stability
  }
  return rightIndex;
}

where arraySwap()&& compare()is defined as

void arraySwap(List *list, int i, int j){

  const void **array = list->array;

  const void *tempPointer = array[i];
  array[i] = array[j];
  array[j] = tempPointer;
}

int compare(const void *key, const void *item){

  if( ((Person *)key)->age < ((Person *)item)->age  ){

    return -1;
  }else if( ((Person *)key)->age > ((Person *)item)->age  ){

    return 1;
  }else{

    return 0;
  }
}

partition()must maintain stability, having additional checks before each arraySwap().

But the output below shows that stability is partially supported (the key 10is stable, unlike the key 50),

$ ./sort.exe
Before sorting
Age,LastName,FirstName
  50  B  A
  30  A  B
  20  X  D
  10  F  A
  50  A  B
  90  V  E
  60  N  M
  10  A  B
After sorting

Age,LastName,FirstName
  10  F  A
  10  A  B
  20  X  D
  30  A  B
  50  A  B
  50  B  A
  60  N  M
  90  V  E

In the function partition() below, a piece of code is just to maintain stability,

while(true){
  ....  
  if( compare(array[leftIndex], array[rightIndex]) == 0 ){
    leftIndex++; rightIndex--;
    continue;                        //Maintain stability
  }
  ....
} 
...      
if( compare(array[pivot], array[rightIndex]) != 0 ){ 
  ... 
}

Question:

Why is the key entry 50unstable?

+4
source share
2 answers

, , , , , , .

, .

+8

. , , :

key  value
2    A
3    B
3    C
1    D
1    E

, (1, 4) (2, 3) , (0, 2), . :

1   D
1   E
2   A
3   C
3   B

, 3 . , , , .

, . , - , , , , .

, . O (N) . , quicksort , , .

+4

Source: https://habr.com/ru/post/1667202/


All Articles