Разработка программы на языке С++ на основе структурной методологии., страница 9

Начнем  с предположения, что первый ключ в этой последовательности (38) служит хорошей  аппроксимацией ключа, который в конечном счете  появится в середине  отсортированной последовательности. Используем это  значение в качестве ведущего элемента, относительно которого ключи  могут меняться местами, и продолжим  следующим образом. Устанавливаем  два указателя I и  J, из которых I начинает отсчет слева (I=1), а J- слева в последовательности (J=N). Сравнивая аI  и аJ. Если  аI aJ ,  устанавливаем J←J−1 и  проводим следующее сравнение. Продолжаем уменьшатьJ  до тех пор, пока не  достигнем аI > аJ. Тогда  поменяем  местами аI aJ (Рис.15, строка 5, обмен ключей 38 и 04),  устанавливаем I←I+1  и   продолжаем увеличивать I  до  тех  пор, пока не получим аI > аJ После следующего  обмена (строка 10, 79 ↔ 38) снова  уменьшаем J. Чередуя  уменьшение J и увеличение I,  продолжаем этот процесс с обоих концов последовательности к «середине» до тех пор, пока не получим I=J.

Теперь имеют место два факта. Во-первых, ключ (38), который сначала  находился в первой позиции, к этому времени занимает  надлежащее место в сортируемой последовательности. Во-первых, все ключи  слева от этого элемента будут меньшими, а все ключи справа – большими.

Ту же процедуру можно применить  к левой  и правой  подпоследовательностям для  окончательной сортировки всей  последовательности. Последняя  строка (с номером 22) рис. 12 показывает, что  когда будет  получено I=J, то I=7. После этого процедура снова применяется к  подпоследовательностям (1,6) и (8,16).

Рекурсивный характер алгоритма наводит на мысль, что  следует значения  индексов крайних элементов большей из двух неотсортированных   подпоследовательностей (8, 16)  поместить на стек и затем перейти к сортировке  меньшей  подпоследовательности (1, 6).

В  строке 4 на рис. 12 число  04 перешло в  позицию 2 и  сортировке подлежат подпоследовательности (1,1) и (3,6). Так как (1,1) уже отсортирована (число 02), сортируем (3,6), что в свою очередь ведет к строке 6 , в которой подлежат сортировке (3,4) и (6,6). В строке 7 подпоследовательность (1,6)  отсортирована. Теперь извлекаем (8,16) из стека и  начинаем сортировку этой  подпоследовательности. В строке 13  находятся подпоследовательности (8,11) и (13,16), которые надо отсортировать. Помещаем (13,16) на стек, сортируем (8,11) и т.д. В строке 20  последовательность целиком  отсортирована.

Прежде чем описать алгоритм  QUICKSORT  формально, нужно точно показать ,как он работает. Мы  пользуемся  стеком [ LEFT (K), RIGHT (K) ]  для   запоминания  индексов крайних левого и правого элементов еще не не отсортированных  подпоследовательностей. Так как  короткие подпоследовательности быстрее сортируются при помощи обычного алгоритма, алгоритм QUICKSORT  имеет входной параметр М, который определяет, насколько короткой  должна бать  подпоследовательность, чтобы ее  сортировать   обычным способом. Для этой цели пользуемся сортировкой  простыми включениями (SIS).

2.3.2. Поиск

Теперь  обратимся  к исследованию некоторых основных проблем, относящихся к поиску информации на  стуктурах данных. Как  и  в предыдущем разделе, посвященному сортировки, будем предполагать, что вся  информация хранится в записях, которые  можно идентифицировать  значениями ключей, т.е. записи Ri  соответствует значение ключа, обозначаемое Ki.

Предположим, что  в файле  расположены случайным образом N  записей  в виде линейного массива. Очевидным   методом поиска заданной записи будет  последовательный просмотр ключей. Если  найден нужный ключ, поиск  оканчивается успешно; в противном случае будут просмотрены все ключи, а поиск  окажется безуспешным. Если  все  возможные  порядки расположения ключей равновероятны, то  такой  алгоритм  требует O(N)  основных операций  как в худшем, так и в среднем случаях. Время  поиска можно заметно уменьшить, если предварительно упорядочить файл по ключам. Эта предварительная работа имеет смысл,  если файл достаточно велик  и  к нему  обращаются часто.