Сортировка с помощью прямого включения. Алгоритмы и структуры данных

Для сортировки (упорядочения) по возрастанию или убыванию значений в массиве разработано множество методов [Вирт, Кнут. т 3].Рассмотрим три из них, считая, для определённости, что первые n, n=6, элементов массива Х

На каждом следующем i-том шаге, i=2, 3,…,n-1, значение из (i+1)-ой ячейки массива путем обмена положением с числом из предыдущей ячейки продвигают в сторону уменьшения индекса ячейки до тех пор, пока ни окажется, что в предыдущей ячейке находится меньшее число.

Из сказанного следует, что при реализации метода прямого включения внешний цикл должен выполняться n-1 раз, а максимально возможное число выполнений внутреннего цикла, в теле которого должны выполняться сравнения и перестановки чисел, будет увеличиваться от 1 до n-1. Однако внутренний цикл следует организовать так, чтобы он заканчивался или вообще не выполнялся при наступлении условия: значение в предыдущей ячейке массива меньше, чем в текущей.

В нашем примере:

При i=2 число 15 из ячейки Х 3 последовательно обменяется местами с числом 34 из ячейки Х 2 , а затем с числом 21 из ячейки Х 1 ,

При i=4 число 25 из ячейки Х 5 обменяется местами с числом 34 из ячейки Х 3 ,

Ниже представлен фрагмент программы упорядочения по возрастанию первых n элементов массива X методом прямоговключения (включения с сохранением упорядоченности) .

    for i:=1 to n-1 do

  1. while (X0) do

  2. R:=X[j];

    X[j]:=X;

    X:=R;

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

Метод прямого обмена (метод пузырька).

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

На первом шаге последовательно, для j = n, n-1, …,2, сравниваются значения соседних ячеек массива, и при выполнении условия Х j <Х j-1 выполняется их перестановка, в результате чего наименьшее число оказывается в ячейке Х 1 .

В нашем примере после выполнения первого шага данные в массиве расположатся так:

На каждом следующем шаге число проверяемых пар ячеек будет уменьшаться на 1. В общем случае, на любом шаге i, i=1, 2, 3, …, n-1, процесс будет выполняться для j от n до i+1, в частности, при i= n-1 – только один раз для n-ой и (n-1)-вой ячеек.

Из сказанного следует, что при реализации метода прямого обмена внешний цикл должен выполняться n-1раз, а число выполнений внутреннего цикла, в теле которого должны выполняться сравнения и перестановки чисел, будет уменьшаться от n-1 до 1.

Происхождение термина “метод пузырька” объясняется так: если представить вертикальное расположение ячеек массива с ростом индекса сверху вниз, то самое маленькое число из рассматриваемых будет подниматься вверх подобно пузырьку в воде.

В нашем примере

При i=3 перестановки приведут к следующему состоянию массива

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

Модифицированный метод прямого обмена (модифицированный метод пузырька).

Как видно из приведенного выше числового примера массив оказался упорядоченным уже после четвёртого шага, то есть возможновыполнение внешнего цикла не n-1 раз, а меньше, когда станет известно, что массив уже упорядочен. Такая проверка основывается на следующем: если при выполнении внутреннего цикла не было ни одной перестановки, значит массив уже упорядочен и можно выйти из внешнего цикла. В качестве признака, выполнялась ли перестановка, используют переменную булевского типа: до входа во внутренний цикл ей дают одно значение, например, False, а при выполнении перестановки – другое, например, True.

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

Сортировка - это расположение данных в памяти в регулярном виде по выбранному параметру. Регулярность рассматривают как возрастание (убывание) значения параметра от начала к концу массива данных.

При обработке данных важно знать информационное поле данных и размещение их в машине.

Различают внутреннюю и внешнюю сортировку:

Внутренняя сортировка - сортировка в оперативной памяти;

Внешняя сортировка - сортировка во внешней памяти.

Если сортируемые записи занимают большой объем памяти, то их перемещение требует больших затрат. Для того, чтобы их уменьшить, сортировку производят в таблице адресов ключей , то есть делают перестановку указателей, а сам массив не перемещается. Это - метод сортировки таблицы адресов.

При сортировке могут встретиться одинаковые ключи. В этом случае желательно после сортировки расположить одинаковые ключи в том же порядке, что и в исходном файле. Это - устойчивая сортировка .

Мы будем рассматривать только сортировки, не использующие дополнительную оперативную память. Такие сортировки называются «на том же месте» .

Эффективность сортировки можно рассматривать по нескольким критериям:

Время, затрачиваемое на сортировку;

Объем оперативной памяти, требуемой для сортировки;

Время, затраченное программистом на написание программы.

Выделяем первый критерий. Эквивалентом затраченного на сортировку времени можно считать количество сравнений и количество перемещений при выполнении сортировки.

Порядок числа сравнений и перемещений при сортировке лежит в пределах

От О (n log n) до О (n 2);

О (n) - идеальный и недостижимый случай.

Различают следующие методы сортировки:

Строгие (прямые) методы;

Улучшенные методы.

Строгие методы:

Метод прямого включения;

Метод прямого выбора;

Метод прямого обмена.

Эффективность строгих методов примерно одинакова.

Сортировка методом прямого включения

Элементы мысленно делятся на уже готовую последовательность a 1 ,...,a i-1 и исходную последовательность.

При каждом шаге, начиная с i = 2 и увеличивая i каждый раз на единицу, из исходной последовательности извлекается i-й элемент и перекладывается в готовую последовательность, при этом он вставляется на нужное место.

Суть алгоритма такова:

for i = 2 to n

X = a(i)

Находим место среди а(1)…а(i) для включения х

next i


Есть два алгоритма сортировки методом прямого включения. Первый - без барьера

Алгоритм сортировки методом прямого включения без барьера

for i = 2 to n

X = a(i)

For j = i - 1 downto 1

If x < a(j)

Then a(j + 1) = a(j)

Else go to L

Endif

Next j

L: a(j + 1) = x

next i

return

Недостатком приведенного алгоритма является нарушение технологии структурного программирования, при которой нежелательно применять безусловные переходы. Если же внутренний цикл организовать как цикл while , то необходима постановка «барьера», без которого при отрицательных значениях ключей происходит потеря значимости и «зависание» компьютера.

Алгоритм сортировки методом прямого включения с барьером

for i = 2 to n

X = a(i)

A(0) = x {a(0) - барьер}

J = i - 1

While x < a(j) do

A(j +1) = a(j)

J = j - 1

Endwhile

A(j +1) = x

next i

return

Эффективность алгоритма прямого включения

Число сравнений ключей Ci при i- м просеивании самое большее равно i-1, самое меньшее - 1; если предположить, что все перестановки из N ключей равновероятны, то среднее число сравнений = i/2. Число же пересылок Mi=Ci+3 (включая барьер). Минимальные оценки встречаются в случае уже упорядоченной исходной последовательности элементов, наихудшие же оценки - когда они первоначально расположены в обратном порядке. В некотором смысле сортировка с помощью включения демонстрирует истинно естественное поведение. Ясно, что приведенный алгоритм описывает процесс устойчивой сортировки: порядок элементов с равными ключами при нем остается неизменным.

Количество сравнений в худшем случае, когда массив отсортирован противоположным образом, С max = n(n - 1)/2, т. е. - О (n 2). Количество перестановок M max = C max + 3(n-1), т.е. - О (n 2). Если же массив уже отсортирован, то число сравнений и перестановок минимально: C min = n-1; M min = =3(n-1).

Сортировка с помощью прямого обмена (пузырьковая сортировка)

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

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

C min = n - 1, порядок О(n),

а перемещения вообще отсутствуют

Сравнительный анализ прямых методов сортировок показывает, что обменная "сортировка" в классическом виде представляет собой нечто среднее между сортировками с помощью включений и с помощью выбора. Если же в нее внесены приведенные выше усовершенствования, то для достаточно упорядоченных массивов пузырьковая сортировка даже имеет преимущество.

Такой метод широко известен под именем "пузырьковая сортировка".


Алгоритм метода прямого обмена

for j = n to i step -1

if a(j) < a(j - 1) then

В нашем случае получился один проход “вхолостую”. Чтобы лишний раз не просматривать элементы, а значит проводить сравнения, затрачивая на это время, можно ввести флажок fl , который остается в значении false , если при очередном проходе не будет произведено ни одного обмена. На нижеприведенном алгоритме добавления отмечены жирным шрифтом.

fl = true

if fl = false then return

fl = false

for j = n to i step -1

if a(j) < a(j - 1) then

fl = true

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

Эффективность алгоритма сортировки прямым обменом

Число сравнений C max = n(n-1)/2 , порядок О(n 2).

Число перемещений М max =3C max =3n(n-1)/2, порядок О(n 2).

Если массив уже отсортирован и применяется алгоритм с флажком, то достаточно всего одного прохода, и тогда получаем минимальное число сравнений

Такой метод широко используется при игре в карты. Элементы (карты) мысленно делятся на уже «готовую» последовательность A 1 , A 2 ,…, A i -1 , и «оставшуюся» (не сортированную) часть: A i , A i +1 ,…, A N .

Суть метода заключается в том, что при каждом i-ом шаге (начиная с i = 2), из неотсортированной части извлекается i-ый элемент и помещается в «готовую» часть, при этом он вставляется на нужное место.

Текстовый алгоритм метода:

1. Начало.

2. Выполнить цикл, пока i имеет значения от 2 до N,
шаг = 1:

а) i-ый элемент (A(i)) поместить в ячейку A(0);

б) присвоить j = -1, то есть j равно номеру элемента, находящегося слева от испытуемого (i-го) и таким образом стоящего в «готовой» последовательности;

в) если А(0) ≥ А(j), то элемент А(0) поместить в ячейку А(j+1), иначе элемент А(j) поместить в ячейку А(j+1), уменьшить значение j на единицу и вновь выполнить пункт в).

На рис. 1 представлена блок-схема сортировки методом прямого включения.

Метод работает следующим образом: на i-ом шаге (начиная с i = 2) i-ый элемент помещается в свободную ячейку (например, А(0)). Этот элемент сравнивается со стоящим в «готовой» части слева от него элементом. Если элемент А(0) меньше, то происходит сдвиг вправо сравниваемого (j-го элемента) на одну позицию, после чего для сравнения берется следующий элемент. Если же элемент А(0) при сравнении оказывается не меньше, то он помещается на место, стоящее сразу за сравниваемым элементом.

Рис. 1. Блок-схема сортировки методом прямого включения

На рис. 2 приведен пример выполнения сортировки методом прямого включения.

Исходная последовательность
А (0)
I = 2
I = 3
I = 4
I = 5
I = 6
I = 7
I = 8
Результат

Рис. 2. Пример сортировки методом прямого включения

Сортировка прямым включением больше подходит для случая, когда сортируемые данные поступают последовательно (одно за другим).

Сортировка методом прямого выбора

Суть метода заключается в следующем. Выбирается наименьший элемент в «оставшейся» (неотсортированной) части и меняется местами с первым элементом (в этой же неотсортированной части). После этого длина неотсортированной части уменьшается на один элемент (на первый), и весь процесс продолжается уже с (n – 1) элементами, затем с (n – 2) элементами и т.д., до тех пор, пока не останется один, самый большой элемент.

Этот метод в некотором смысле противоположен методу прямого включения. В методе прямого включения на каждом шаге рассматривается только один очередной элемент и все элементы уже «готовой» части последовательности, среди которых отыскивается точка включения этого очередного элемента. А в методе прямого выбора для поиска одного (минимального) элемента просматривают все элементы неотсортированной части, и этот минимальный элемент помещается как очередной элемент в уже «готовую» часть.

Текстовый алгоритм метода:

1. Начало.

2. Выполнить цикл, пока i имеет значения от 1 до N – 1,
шаг = 1:

а) поместим текущий (i-ый) элемент в какую-нибудь ячейку памяти (Х) и запомним порядковый номер (i) текущего элемента (в переменной К);

б) выполнить цикл, пока j имеет значения от i + 1 (то есть от следующего за i элемента) до N, шаг = +1:

тело цикла: если Х > А(j), то помещаем в ячейку Х элемент А(j) и запоминаем его номер в ячейке К;

в) присвоить А(К) = А(i) и А(i) = Х.

На рис. 3 приведен пример выполнения сортировки методом прямого выбора.

Исходная последовательность 44 06
I = 1 55 12
I = 2 55 18
I = 3 42 55
I = 4 94 44
I = 5 55 94
I = 6 94 67
I = 7

Рис. 3. Пример сортировки методом прямого выбора

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

Рассмотрим j ‑й шаг сортировки (j =2, 3, ..., n ). Если K [ j ]>= K [ j -1] , то упорядоченность не нарушилась и следует перейти к R [ j +1]– ой записи. Если же K [ j ]< K [ j -1] , то R [ j ] запоминается в рабочей переменной (Rab = R [ j ]) и для нее ищется место в упорядоченной части таблицы – в подтаблице. Обозначим нижнюю границу индекса этой подтаблицы через ng , верхнюю - через vg (первоначально ng =1. vg =j-1 ).

Согласно бинарному поиску ключ K [ j ] рассматриваемой записи R [ j ] должен сначала сравниться с ключом K [ i ] записи R [ i ] , находящейся в середине упорядоченной подтаблицы (i=(ng+vg) div 2) . Если K [ j ]> K [ i ], то отбрасывается (то есть больше не рассматривается) левая часть подтаблицы- записи с меньшими ключами (ng = i +1) . Если K [ j ]< K [ i ] , то отбрасывается правая часть подтаблицы - записи с большими ключами (vg = i -1). В оставшейся части подтаблицы поиск продолжается. Процесс деления частей подтаблицы пополам продолжается до тех пор, пока не возникнет одна из следующих ситуаций:

1) K [ j ]= K [ i ] , следовательно, (i+1) -я позиция является местом для рассматриваемой записи. Сдвинем записи R [ i +1], R [ i +2], …, R [ j -1] на одну позицию вправо и освободим тем самым место для вставки (R [ i +1]= Rab ).

2) K [ j ]<> K [ i ] и ng > vg – ключи не совпали, а длина последней подтаблицы равна 1. В этом случае местом для вставки является позиция ng , поэтому записи R [ ng ], R [ ng +1], … , R [ j -1] должны быть сдвинуты на одну позицию вправо (R [ ng ]= Rab ) .

Алгоритм бинарного поиска подробно описан в разделе "Дихотомический поиск по совпадению".

Рассмотрим на примере j -й шаг сортировки (определяется место записи с ключом, равным 9; j =7, K [ j ]=9 ):

Среднее число сравнений для данного метода составляет n log 2 (n) .

Метод двухпутевой вставки

Метод двухпутевой вставки является модификацией метода вставки с прямым включением; он позволяет улучшить характеристики сортировки.

Для реализации этого метода необходим дополнительный объем памяти, равный объему, занимаемому таблицей, подлежащей сортировке (назовем его зоной вывода T ). На первом шаге сортировки в середину зоны вывода (позиция m=(n div 2)+1 ) помещается первая запись таблицы R. Остальные позиции Т пока пусты. На последующих шагах сортировки ключ очередной записи R [ j ] (j =2, 3, …, n ) сравнивается с ключом записи T [ m ] и, в зависимости от результатов сравнения, место для R [ j ] отыскивается в Т слева или справа от T [ m ] методом вставки. При этом должны запоминаться номера самого левого (l ) и самого правого (r ) внесенных в зону вывода элементов. Конечные значения l и r равны 1 и n соответственно.

В алгоритме должны быть учтены также следующие ситуации:

    ключ записи R[j] меньше ключа записи T[m] , но l=1 ;

    ключ записи R[j] больше ключа записи T[m] , но r=n .

В этих случаях для вставки записи R [ j ] необходимо осуществлять сдвиг записей подтаблицы вместе с записью T [ m ] вправо или влево (используется метод вставки с прямым включением).

Рассмотрим пример сортировки с использованием этого метода.

Пусть исходная последовательность ключей таблицы имеет вид:

24, 1, 28, 7, 25, 3, 6, 18, 8 (n =9, m =(n div 2)+ 1=5)

Номер шага

Зона вывода

Необходимые определения и классификация сортировок.

Сортировка. Необходимые определения и классификация сортировок. Сортировки прямого включения и выбора. Их эффективность

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

Если сортируемые записи занимают большой объем памяти, то их перемещение требует больших затрат. Для того чтобы их уменьшить, используют метод сортировки таблицы адресов . Этот метод применяют в таблице адресов ключей . Производят перестановку указателей, т.е. Сам массив не перемещается. При сортировке могут встретиться и одинаковые ключи. В этом случае одинаковые ключи желательно расположить после сортировки в том же порядке, что и в исходном файле. Этот принцип используется для устойчивой сортировки .

Эффективность сортировки можно рассматривать с нескольких критериев:

1) время, затрачиваемое на сортировку;

2) объем оперативной памяти, требуемой для сортировки;

3) время, затраченное программистом на написание программы.

Время, затраченное на сортировку, пропорционально количеству сравнений при выполнении сортировки и количеству перемещений элементов.

Считается, что порядок числа сравнения при сортировке может находиться в пределах от о(nlogn) до о(n 2) , где о(n) - идеальный и недостижимый случай.

Методы сортировки можно классифицировать примерно так:

1) строгие (прямые) методы (их эффективность примерно одинакова):

· прямого включения ;

· прямого выбора ;

· прямого обмена ;

2) улучшенные методы .

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

Элементы мысленно делятся на уже готовую последовательность a 1 ,...,a i-1 и исходную последовательность. В готовой последовательности элементы располагаются в заданном порядке (по убыванию или по возрастанию). А в исходной последовательности располагаются элементы, которые и нужно отсортировать. При каждом шаге элементы исходной последовательности уменьшаются на единицу, а готовая увеличивается на единицу. Это происходит из-за того, что из исходной последовательности извлекается i- й элемент и перекладывается в готовую последовательность, при этом он вставляется на нужное место среди элементов готовой последовательности.

Рассмотрим пример сортировки методом прямого включения на последовательности элементов: 10, 3, 11, 8, 2, 15, 44, 9 (табл. 11.1). Необходимо её отсортировать по возрастанию.

Сначала готовая последовательность не имеет элементов. На первом шаге первый элемент исходной последовательности – это 10, становится первым элементом готовой последовательности. Далее второй шаг: элемент 3 из исходной последовательности помещается в готовую. Это происходит так. Если элемент больше 10, то он остаётся на своём месте, а если меньше, то 10 сдвигается на единицу вправо и на её место ставится элемент. Так как 3<10, то готовая последовательность теперь будет иметь вид: 3, 10, а исходная – 11, 8, 2, 15, 44, 9. Далее на третьем шаге из исходной последовательности выбирается 11 и помещается в готовую последовательность. Сначала 11 сравнивается с 10, и так как 11>10, то 11 остаётся на месте. Исходная последовательность теперь равна: 8, 2, 15, 44, 9. Последующие шаги производятся аналогичным образом.

Таблица 11.1

Принцип работы сортировки прямым включением

Число шагов в данной сортировке (табл. 11.1) равно числу элементов в сортируемой последовательности, т.е. 8 шагов = 8 элементов.

Существуют два способа реализации данного метода – это без барьера (рис. 11.1) и с барьером (рис. 11.2).