Ниже partition()
логика используется 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;
}
где arraySwap()
& & compare()
определяется как,
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()
должен поддерживать стабильность, имея дополнительные проверки перед каждый arraySwap()
.
Но ниже выхода показывает, что стабильность частично сохраняется (ключ 10
стабилен в отличие от ключа 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
В функции partition()
, ниже кода фрагмента, чтобы просто поддерживать стабильность,
while(true){
....
if(compare(array[leftIndex], array[rightIndex]) == 0){
leftIndex++; rightIndex--;
continue; //Maintain stability
}
....
}
...
if(compare(array[pivot], array[rightIndex]) != 0){
...
}
Вопрос:
Почему запись с ключом 50
нестабильна?
Запрос обновлен с дополнительным описанием. По вашему мнению, * шаг раздела может заменять элементы, которые сравниваются друг с другом *. Если вы видите код, 'partiotion()' не разрешает 'arraySwap()', когда элементы равны. Вы согласны? – overexchange
ОК, я был слишком точным: шаг раздела не меняет элементы, сравнивающие одинаковые, но может перемещать элемент из левой части в правую часть, за другим сравниваемым с ним элементом, эффективно изменяя их порядок в массив и наоборот. – chqrlie
В равной степени, вы имеете в виду 'size = 1' sub array? Я не разделяю под массивом 'size = 1'. Обновленный запрос. Вероятно, я не получил ваш комментарий. – overexchange