Вы пытаетесь реализовать быструю сортировку для связанных списков на основе уже существующей реализации для массивов. Вы делаете это, меняя значения узлов. На мой взгляд, это не идеально. Связанные списки не являются массивами. Вместо этого вы должны поменять местами узлы.
(Вероятно, причина в том, что ваши данные существуют в виде связанного списка. Если полезная нагрузка на узлы велика, обмен данными неэффективен. Если у вас есть внешние указатели на узлы, подкачка сделает их недействительными.)
Как работает быстрая сортировка?
- Выберите сводку и удалите ее из списка.
- Разделите оставшийся список на
- элементов, которые меньше, чем элементы pivot ( le ),
- , равные элементу pivot, и элементы
- , превышающие значение элемента pivot ( gt ) на несколько метри c.
- Запустите quicksort для разделов, чтобы ваш список теперь выглядел следующим образом:
sorted le partition | стержень | sorted gt partition
В реализации массива вы достигнете этого, меняя элементы вокруг и перемещая шарнир. Это хорошая стратегия, потому что таким образом вам нужно дополнительное пространство.
В связанном списке вы можете создавать разделы, извлекая текущий список в два списка разделов. Вызовите их с помощью быстрой сортировки, а затем снова соедините их вместе с центральной точкой.
Если у вас есть списки с множеством элементов, которые имеют одинаковое значение, т. Е. Сравнивают одинаково, вы можете сделать одноузловую точку третий список, eq .
Вот код, который делает это. Функции
pop
, которые выводят первый узел из списка; append
, который добавляет узел в конец списка, и join
, который добавляет второй список к первому
, не отображаются, но сам алгоритм должен быть понятным. Это довольно просто. Каждый узел имеет next
и ´prev pointer as well as some
data ; a list has
head and
tail` указатели.
В любом случае, здесь идет:
void quicksort(List *list)
{
if (list->head != list->tail) {
List eq = {NULL, NULL};
List lt = {NULL, NULL};
List gt = {NULL, NULL};
append(&eq, pop(list));
while (list->head) {
Node *node = pop(list);
int cmp = compare(node->data, eq.head->data);
if (cmp < 0) {
append(<, node);
} else if (cmp > 0) {
append(>, node);
} else {
append(&eq, node);
}
}
quicksort(<);
quicksort(>);
join(list, <);
join(list, &eq);
join(list, >);
}
}
Этот метод сортировки стабилен : Элементы с одинаковым значением имеют одинаковый порядок в отсортированном и исходном списке. Полный пример программы, которая включает в себя функции pop
, join
и extract
: здесь на ideone .