Как исправить этап Conquer этой итеративной реализации быстрой сортировки по примеру Khan Academy?

В образовательных целях я пытаюсь изучить алгоритм быстрой сортировки. Вместо того, чтобы проверять реализацию в Интернете или пытаться реализовать непосредственно из псевдокода в Википедии, Я пробую "жесткий путь".

Я смотрел эту лекцию из CS50 https://www.youtube.com/watch?v=aQiWF4E8flQ&t=305s, чтобы понять, как перемещаются числа при «быстрой сортировке». Моя реализация, которую я покажу ниже, отлично работает для примера, представленного на видео. Пример на видео исходного несортированного массива таков:

введите здесь описание изображения

Это мой код в Python 3:

len_seq = int(input())

print("len_seq",len_seq)

seq_in = list(map(int,(input()).split()))

print("seq_in",seq_in)

def my_quick_sort(seq):

    wall_index = 0

    pivot_corect_final_index_list = [] 

    while wall_index<len_seq:

        pivot = seq[-1]
        print("pivot",pivot)

        print("wall_index",wall_index)

        for i in range(wall_index,len_seq):
            print ("seq[i]",seq[i])
            if seq[i]<pivot:
                print("before inside swap,", seq)
                seq[wall_index],seq[i]=seq[i],seq[wall_index]
                print("after inside swap,", seq)
                wall_index = wall_index + 1
                print ("wall_index",wall_index)

        print("before outside swap,", seq)

        seq[wall_index],seq[-1]=seq[-1],seq[wall_index]
        print("after outside swap,", seq)

        pivot_corect_final_index = wall_index
        print ("pivot correct final index",pivot_corect_final_index)

        pivot_corect_final_index_list.append(pivot_corect_final_index)
        print ("pivot_corect_final_index_list",pivot_corect_final_index_list)

        wall_index = wall_index + 1
        print ("wall_index",wall_index)


    return seq

print(my_quick_sort(seq_in))

Чтобы использовать пример Гарварда CS50 в моем коде, вам нужно ввести это:

9
6 5 1 3 8 4 7 9 2

Алгоритм работает нормально и возвращает правильный результат:

[1, 2, 3, 4, 5, 6, 7, 8, 9]

Продолжая свое исследование, я попытался реализовать пример Академии Хана: https://www.khanacademy.org/computing/computer-science/algorithms/quick-sort/a/overview-of-quicksort

Несортированный список в этом случае:

[9, 7, 5, 11, 12, 2, 14, 3, 10, 6]

Вам нужно ввести следующее в мой код, чтобы запустить его:

10
9 7 5 11 12 2 14 3 10 6

В отличие от гарвардского примера, в данном случае моя реализация работает неидеально. Он возвращает:

[5, 2, 3, 6, 7, 9, 10, 11, 12, 14]

Как видите, все числа, которые я рассматривал как опорные, заканчиваются в правильной позиции. Однако некоторые числа за разворотами неверны.

Читая статью академии хана, кажется, что моя реализация правильная на этапе разделения. Однако она неверна на этапе завоевания. Я стараюсь не искать окончательного решения. Я пытаюсь улучшить то, что я построил до сих пор. Не уверен, что это лучший метод, но сейчас я его пробую.

Как я могу исправить шаг завоевания? Нужно ли внедрять рекурсивный подход? Как я могу сделать это внутри моего итеративного процесса? И следует ли вводить этот шаг после успешного лечения каждого поворота?

Спасибо за терпение при чтении этого длинного поста.


person Community    schedule 03.06.2017    source источник


Ответы (1)


Не могу комментировать, недостаточно репутации.

В первом проходе вашего алгоритма вы правильно размещаете все элементы, меньшие, чем опорная точка, слева от опорной точки. Однако, поскольку ваше значение wall_index увеличивается (например, с 0 до 1), вы игнорируете самый левый элемент с индексом 0 (он может быть не в правильном положении, поэтому его не следует игнорировать).

В тестовом примере Академии Хана число 5 помещается в крайний левый индекс при первом проходе, а затем игнорируется при последующих проходах, поэтому оно застревает слева. Точно так же, попробовав эту модификацию гарвардского примера

9
6 5 1 3 8 4 7 2 9

урожаи

[6, 5, 1, 3, 8, 4, 7, 2, 9]

После первого разделения вы должны обязательно применить быструю сортировку к обоим массивам слева и справа от опорной точки. Например, после того, как первая опорная точка (6) будет помещена в правильное положение для примера Хана (то, что вы обозначили как внешний обмен),

[5, 2, 3, 6, 12, 7, 14, 9, 10, 11]
 <--1-->  p  <--------2--------->

вам нужно применить одну и ту же быструю сортировку к обоим подмассивам 1 и 2 на диаграмме выше. Я предлагаю вам сначала попробовать рекурсивную реализацию, которая даст вам хорошее представление об алгоритме, а затем попытаться реализовать его итеративно.

person codelessbugging    schedule 08.06.2017