Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Metodichka_OAiP.doc
Скачиваний:
30
Добавлен:
11.05.2015
Размер:
1.61 Mб
Скачать

5. Сортировка методом Хоора

Сортировка методом Хоора (или быстрая сортировка) — это наиболее эффективный алгоритм внутренней сортировки. Его производительность зависит от выбора точки разбиения. При быстрой сортировке используется следующая стратегия:

1. Массив разбивается на меньшие подмассивы.

2. Подмассивы сортируются.

3. Отсортированные подмассивы объединяются.

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

Рассмотрим один из вариантов реализации сортировки Хоора.

Пример 15.6

В самой процедуре сортировки сначала выберем средний элемент. Потом, используя переменные i и j, пройдемся по массиву, отыскивая в левой части элементы больше среднего, а в правой – меньше среднего. Два найденных элемента переставим местами. Будем действовать так, пока i не станет больше j. Тогда получаем два подмножества, ограниченные с краев индексами l и r, а в середине – j и i. Если эти подмножества существуют (то есть i<r и j>l), то выполним их сортировку.

void Quicksort(int a[], int n, int left, int right)

{ int i=left, j=right; /*Инициализируем переменные левой и

правой границами подмассива*/

int test=a[(left+right)/2]; /*Выбираем в качестве

элемента разбиения средний элемент массива*/

do { while (a[i] < test)

i++;

/*находим элемент, больший элемента разбиения */

while (a[j] > test)

j--;

/*находим элемент, меньший элемента разбиения */

if (i<=j)

{ Swap(&a[i], &a[j);

i++; j--; }

}

while(i <= j); /*рекурсивно вызываем алгоритм для

правого и левого подмассива*/

if (i<right)

QuickSort(a, n, i, right);

if (j>left)

QuickSort(a, n, left, j);

}

Анализ быстрой сортировки

Быструю сортировку следует рассмотреть одной из первых при выборе метода внутренней сортировки. Алгоритм этой сортировки содержит сложную фазу разбиения и простую фазу слияния. В худшем случае выполненная работа эквивалентна работе при сортировке выбором. Производительность быстрой сортировки существенно зависит от выбора точки разбиения.

6. Алгоритмы поиска

6.1. Последовательный поиск

Задача поиска. Пусть заданы линейные списки: список элементов В=<К1,К2,К3,...,Кn> и список ключей V= (в простейшем случае это целые числа). Требуется для каждого значения Vi из V найти множество всех совпадающих с ним элементов из В. Чаще всего встречается ситуация, когда V содержит один элемент, а в В имеется не более одного такого элемента.

Эффективность некоторого алгоритма поиска А оценивается максимальным Max{А} и средним Avg{А} количествами сравнений, необходимых для нахождения элемента V в В. Если Pi – относительная частота использования элемента Кi в В, а Si – количество сравнений, необходимое для его поиска, то

n

Max{А} = max{ Si, i=1,n } ; Avg{А} = Pi Si .

i=1

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

Очевидно, что Max последовательного поиска равен N. Если частота использования каждого элемента списка одинакова, т.е. P=1/N, то Avg последовательного поиска равно N/2. При различной частоте использования элементов Avg можно улучшить, поместив часто встречаемые элементы в начало списка.

Пример 15.7

Пусть во входном потоке задано 5 целых чисел К1,К2,... К5 и ключ V. Составим программу для последовательного хранения элементов Кi и поиска среди них элемента, равного V, причем такого элемента может и не быть в списке. Без использования стоппера программа может быть реализована следующим образом:

#include <stdio.h>

void main(void)

{

int k[5],v,i,count=0;

puts(“Vvedite elementi:”);

for (i=0;i<5;i++)

scanf(“%d”,&k[i]);

puts(“vvedite element dlja poiska”);

scanf(“%d”,&v);

i=0;

while(i<5)

{ if (k[i]==v)

{

printf(“element-%d position-%d\n”,v,(i+1));

count++;

}

i++;

}

if(count==0) printf(“element-%d ne naiden “,v);

}

6.2. Поиск элемента по индексу

Пример 15.8

#include <stdio.h>

void main(void)

{     int k[5],v,i,count=0;

puts("Vvedite elementi:");

for (i=0;i<5;i++)

scanf("%d",&k[i]);

puts("vvedite element dlja poiska");

scanf("%d",&v);

i=0;

while(i<5)

{

if (k[i]==v)

{

printf("element-%d position-%d\n",v,(i+1));

count++;

}

i++;

}

if(count==0) printf("element-%d ne naiden ",v);

puts("Vvedite index elementa");

scanf("%d",&v);

if(v>=0&&v<5)

printf("element s indexom %d raven = %d\n",v,k[v]);

else printf("Elementa s takim indexom net\n");

}

Анализ линейного поиска

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

6.3. Бинарный поиск

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

Нахождение элемента бинарным поиском осуществляется очень быстро. Max бинарного поиска равен log2(N), и при одинаковой частоте использования каждого элемента Avg бинарного поиска равен log2(N). Недостаток бинарного поиска заключается в необходимости последовательного хранения списка, что усложняет операции добавления и исключения элементов.

Пример 15.9

#include <stdio.h>

void main()

{

int k[6];

int v, i, j, m;

for (i=0;i<6;i++)

scanf("%d",&k[i]);

scanf("%d",&v);

i=0;

j=6;

m=3;

while (k[m]!=v)

{

if (k[m] < v)

i+=m;

else j=m-i;

m=(i+j)/2;

}

printf("%d %d",v,m);

}

Соседние файлы в предмете [НЕСОРТИРОВАННОЕ]