Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Лекции / LECS15.DOC
Скачиваний:
43
Добавлен:
16.04.2013
Размер:
114.18 Кб
Скачать

В файле vectacum. Cpp

// Простой численный алгоритм

int accumulate // сумма значений контейнера

( vector :: iterator first, // начальная позиция

vector :: iterator last, // конец

int initial_val // начальное значение

)

{

vector :: iterator p;

int sum = initial_val;

for (p = first; p != last; ++p)

sum += *p;

return sum:

}

Обратите внимание, что last обозначает конец диапазона; сама переменная last не разыменовывается. Вот почему функция - член vector :: end ( ) возвращает p + size.

Пример: quicksort ( )

Процедура сортировки quicksort (быстрая сортировка), которую изобрел

Энтони Хор (Anthony Hoare), является высокоэффективной внутренней сортировкой. Ее сложно запрограммировать из-за многочисленных индексов, которые отслеживаются в традиционной реализации (см. книгу Kelly and Pohl, A Book on C: 3rd Edition, Benjamin/ Cummings, 1995). Мы заменим индексирование итераторами.

Алгоритм quicksort работает, рекурсивно разбивая неупорядоченные значения на два подмножества, разделенные неким средним значением (mid - value). Среднее значение больше, чем все элементы в первом подмножестве, и меньше или равно любого элемента второго подмножества. Такое разделение приводит ко все уменьшающимся подмножествам, которые в свою очередь разделяются до тех пор, пока не отсортируются тривиальным образом. Применение процедуры quicksort служит иллюстрацией эффективности метода «разделяй и властвуй» в программировании.

В файле vectsort. Cpp

// QUICKSORT, использующая итератор

void quicksort (vector :: iterator from, vector :: iterator to)

{

vector :: iterator mid;

if (from < to – 1) {

mid = partition (from, to); // произвести разделение

quicksort (from, mid); // в диапазоне от from до to

quicksort (mid +1, to); // mid - “середина”

}

}

vector :: iterator partition (vector :: iterator from, vector :: iterator to)

{

vector :: iterator front = from + 1, back = to –1;

int compare = *from;

while (front < back) {

// поиск элемента не на месте (вперед)

while ((front < back) && (compare > *front))

++front;

// поиск элемента не на месте (назад)

while ((front < back) && (compare <= *back))

--back;

swap (*front, *back);

}

// вставка среднего элемента для сравнения

if (compare > *front) {

swap (*from, *front);

return front;

}

else {

swap (*from, *(front – 1));

return front – 1;

}

}

Настоящая работа происходит в функции partition (). Она «волевым решением» использует первый элемент в качестве основы для разделения элементов на части «меньше, чем» и «больше или равно, чем». Когда она находит элемент «не на месте», расположенный на стороне «меньше, чем», она переключается на поиски элемента «не на месте», который находится на стороне «больше, чем».

Она меняет эти элементы местами попарно до тех пор пока не закончит разделение, как показано на следующем рисунке.

front compare = 10 back

 

10

7

16

4

9

18

-3

8

12

front back

 

10

7

16

4

9

18

-3

8

12

swap swap

 

10

7

8

4

9

18

-3

16

12

front back

 

10

7

16

4

9

-3

18

16

12

повторный вызов mid повторный вызов

  

-3

7

8

4

9

10

18

16

12

Функция swap ( ) меняет местами неотсортированные элементы. Сделав функцию swap ( ) встроенной, мы придадим коду внутреннего цикла в

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

inline void swap (int& i, int& j)

{

int temp = i;

i = j;

j = temp;

}

В разделе 9.5, «Параметризация quicksort ( )», на стр. 254 мы покажем, как превратить этот код в обобщенный алгоритм, который содержится в STL.

Соседние файлы в папке Лекции