Алгоритм быстрой сортировки можно разделить на следующие шаги
Определить опору.
Разделите связанный список на основе сводки.
Разделите связанный список рекурсивно на 2 части.
Теперь, если я всегда выбираю последний элемент как сводный, то для идентификации сводного элемента (1-й шаг) требуется времени.
После определения сводного элемента мы можем сохранить его данные и сравнить их со всеми остальными элементами, чтобы определить правильную точку разбиения (2-й шаг). Каждое сравнение будет занимать время, поскольку мы храним сводные данные, а каждый обмен занимает время. Таким образом, в общей сложности требуется время для элементов.
Таким образом, отношение повторения:
что такое же, как в сортировке слиянием со связанным списком.
Так почему сортировка слиянием предпочтительнее быстрой сортировки для связанных списков?
Ответы:
Схема доступа к памяти в Quicksort является случайной, также имеется готовая реализация, поэтому она использует много перестановок, если ячейки достигают упорядоченного результата.
В то же время сортировка слиянием является внешней, для получения упорядоченного результата требуется дополнительный массив. В массиве это означает дополнительные затраты пространства, в случае связанного списка, можно извлечь значение и начать объединение узлов. Доступ более последовательный по своей природе.
Из-за этого быстрая сортировка не является естественным выбором для связанного списка, в то время как сортировка слиянием имеет большое преимущество.
Обозначения Ландау могут (более или менее, потому что быстрая сортировка по-прежнему равна ), но константа намного выше.O(n2)
В среднем случае оба алгоритма находятся в поэтому асимптотический случай один и тот же, но предпочтение строго обусловлено скрытой константой, и иногда возникает проблема стабильности (быстрая сортировка по своей природе нестабильна, mergsort стабильна).O(nlogn)
источник
Вы можете быстро отсортировать связанные списки, однако вы будете очень ограничены с точки зрения выбора сводки, ограничивая вас сводками рядом с передней частью списка, что плохо для почти отсортированных входных данных, если только вы не хотите перебирать каждый сегмент дважды (один раз для сводки и один раз за раздел). И вам нужно будет сохранить стек границ разделов для списков, которые вам еще нужно отсортировать. Этот стек может вырасти до когда выбор оси вращения плох, а сложность времени возрастает до O ( n 2 ) .O(n) O(n2)
Это алгоритм, который ядро Linux использует для сортировки связанных списков. Хотя с некоторыми дополнительными оптимизациями, такими как игнорирование
previous
указателя во время всего, кроме последней операции слияния.источник
Вы можете написать сортировку слиянием, сортировку по разделам, сортировку по дереву и сравнить результаты.
Довольно легко написать сортировку по дереву, если вы оставите немного свободного места.
Для сортировки по дереву каждый узел связанного списка должен иметь два указателя, даже если мы сортируем односвязный список
в связанном списке. Я предпочитаю вставлять и удалять вместо
перестановки раздел Hoare можно сделать только для двусвязного списка
Этот код нуждается в некоторых улучшениях.
Во-первых, мы должны ограничить дополнительное пространство для нужд рекурсии,
затем мы должны попытаться заменить рекурсию итерацией.
Если мы хотим улучшить алгоритм дальше, мы должны использовать самобалансировочное дерево
источник
Быстрая сортировка
Может быть, я покажу шаги для быстрой сортировки
Если список содержит более одного узла
Первый подсписок содержит узлы с ключами, меньшими, чем сводный ключ.
Второй подсписок содержит узлы с ключами, равными сводному ключу.
Третий подсписок содержит узлы с ключами, превышающими сводный ключ
Объявление 1.
Если мы хотим выбрать pivot fast, выбор ограничен.
Мы можем выбрать головной узел или хвостовой узел.
Наш список должен иметь указатель на узел, если мы хотим, чтобы наш pivot
был быстро доступен, в противном случае мы должны искать узел.
Объявление 2.
Мы можем использовать операции очереди для этого шага.
Сначала мы удаляем узел из исходного связанного списка,
сравниваем его ключ с ключом поворота и ставим в очередь узел с правильным подсписком.
Списки создаются из существующих узлов, и нет необходимости
выделять память для новых узлов.
Указатель на хвостовой узел будет полезен, потому что операции с очередями
и конкатенация выполняются быстрее при наличии этого указателя
источник