- •Предназначено студентам очной формы обучения.
- •Введение
- •1. Оценки сложности алгоритмов
- •1.1. Определение понятия алгоритм
- •1.2. Оценка сложности алгоритмов
- •2. Линейные структуры данных
- •2.1. Методы организации и хранения линейных списков
- •2.2. Операции со списками при последовательном хранении
- •2.3. Операции со списками при связном хранении
- •2.4. Организация двусвязных списков
- •Задания для самоконтроля
- •2.5. Стеки и очереди
- •2.6. Сжатое и индексное хранение линейных списков
- •3. Сортировка и слияние
- •3.1. Пузырьковая сортировка
- •3.2. Сортировка вставкой
- •3.3. Сортировка посредством выбора
- •3.4. Сортировка квадратичной выборкой
- •3.5. Слияние списков
- •3.6. Сортировка списков путем слияния
- •3.7. Быстрая и распределяющая сортировки
- •4. Поиск
- •4.1. Последовательный поиск
- •4.2. Бинарный поиск
- •4.4. Методы вычисления адреса
- •4.5. Выбор в линейных списках
- •5. Рекурсия
- •6. Алгоритмы на графах и сетях
- •6.1. Исходные понятия
- •6.2. Матричные представления графов
- •6.3. Другие представления графов
- •6.4. Поиск в глубину как система исследования графа
- •6.5. Перебор цепей поиском в глубину
- •6.6. Взвешенные графы. Ориентированные графы
- •6.7. Нахождение фундаментального множества циклов
- •6.8. Выявление мостов и точек сочленений
- •6.9. Поиск в ширину как система исследования графа
- •6.10. Кратчайшие пути, ведущие от заданного узла X ко всем прочим
- •6.11. Алгоритм Дейкстры нахождения кратчайших путей во взвешенном графе
- •6.12. Улучшения алгоритма Дейкстры
- •6.13. Построение кратчайшего каркаса
- •6.14. Нахождение всевозможных кратчайших путей в графе
- •6.15. Потоковые задачи
- •6.16. Пример практической задачи на графах
- •7. Генераторы случайных и псевдослучайных последовательностей
- •7.1. Общая постановка задачи
- •7.3. Генератор случайных чисел, поставляемый с системой
- •7.4. Генератор с малым кодом
- •7.5. Генератор Парка-Миллера
- •7.6. Улучшенная версия генератора Парка-Миллера
- •7.7. Быстрый генератор для 32-битового представления целых и действительных чисел
- •7.8. Алгоритм л'Экюера, комбинирующий две последовательности
- •Оглавление
- •7. Генераторы случайных и псевдослучайных последовательностей 144
- •394026 Воронеж, Московский просп., 14
3.2. Сортировка вставкой
Упорядоченный массив B' получается из В следующим образом: сначала он состоит из единственного элемента K1; далее для i=2, ..., N выполняется вставка узла Ki в B' так, что B' остается упорядоченным списком длины i.
Например, для начального списка B=< 20,-5,10,8,7 > имеем:
B=< 20, -5, 10, 8, 7> B'=<>
B=< -5, 10, 8, 7 > B'=< 20 >
B=< 10, 8, 7 > B'=< -5, 20 >
B=< 8, 7 > B'=< -5, 10, 20 >
B=< 7 >B'=< -5, 8, 10, 20 >
B=<>B'=< -5, 7, 8, 10, 20 >
Функция insert реализует сортировку вставкой.
/*сортировкаметодомвставки*/
float *insert(float *s, int m, int n)
{
int i,j,k;
float aux;
for (i=m+1; i<=n; i++)
{
aux=s[i];
for (k=m; ((k<=i) && (s[k]<aux)); k++)
s[k]=aux;
}
return(s);
}
Здесь оба списка В и В' размещаются в массиве s, причем список В занимает часть s c индексами от i до n, а B' - часть s c индексами от m до i-1(рис.15).
При сортировке вставкой требуется O((n-m)*(n-m)) сравнений и не требуется дополнительной памяти.
Рис. 15. Схема движения индексов при сортировке вставкой
3.3. Сортировка посредством выбора
Упорядоченный список В' получается из В многократным применением выборки из В минимального элемента, удалением этого элемента из В и добавлением его в конец списка В', который первоначально должен быть пустым.
Например:
B=<20,10,8,-5,7>, B'=<>
B=<20,10,8,7>, B'=<-5>
B=<20,10,8>, B'=<-5,7>
B=<20,10>, B'=<-5,7,8>
B=<20>, B'=<-5,7,8,10>
B=<>, B'=<-5,7,8,10,20> .
Функция select упорядочивает массив s сортировкой посредством выбора.
/*сортировкаметодомвыбора*/
double *select( double *s, int m, int n)
{
int i,j;
double c;
for (i=m; i<n; i++)
for (j=i+1; j<n; j++) if(s[j]<s[i])
{
c=s[i];
s[i]=s[j];
s[j]=c;
}
return(s);
}
Здесь, как и в предыдущем примере оба списка В и В' размещаются в разных частях массива s (рис.16). При сортировке посредством выбора требуется O((n-m)*(n-m)) действий и не требуется дополнительной памяти.
Рис. 16. Схема движения индексов при сортировке выбором
3.4. Сортировка квадратичной выборкой
Исходный список В из N элементов делится на М подсписков B1, B2, ..., Bm, где М= , и в каждом B1 находится минимальный элемент G1. Наименьший элемент всего списка В определяется как минимальный элемент Gj в списке, и выбранный элемент Gj заменяется новым наименьшим из списка Bj. Количество действий, требуемое для сортировки квадратичной выборкой, несколько меньше, чем в предыдущих методах O( ), но требуется дополнительная память для хранения списка G.
3.5. Слияние списков
Упорядоченные списки А и В длин М и N сливаются в один упорядоченный список С длины М+N, если каждый элемент из А и В входит в С точно один раз. Так, слияние списков А=<6, 17, 23, 39, 47> и В=<19, 25, 38, 60> из 5 и 4 элементов дает в качестве результата список С=<6, 17, 19, 23, 25, 38, 39, 47, 60> из 9 элементов.
Для слияния списков А и В список С сначала полагается пустым, а затем к нему последовательно приписывается первый узел из А или В, оказавшийся меньшим и отсутствующий в С.
Составим функцию для слияния двух упорядоченных, расположенных рядом частей массива s. Параметром этой функции будет исходный массив s с выделенными в нем двумя расположенными рядом упорядоченными подмассивами: s (low), s (low+1), …, s (low+l-1); s (low+l), s (low+l+1), …, s (up), где переменные low, l, up указывают месторасположения подмассивов. Функция merge осуществляет слияние этих подмассивов, образуя на их месте упорядоченный массив s (low), s (low+1), …, s (up-1), s (up).
/* слияниесписков */
double *merge(double *s, int low, int up, int l)
{
double v;
int i,j,k;
for(i=low; i<low+l; i++)
{
for(j=low+l; j<=up; j++)
{
if( s[i]>s[j])
{
v=s[j];
s[j]=s[i];
s[i]=v;
k=j;
while((k+1!=up) && (s[k]>s[k+1]))
{
v=s[k+1];
s[k+1]=s[k];
s[k++]=v;
}
}
}
}
returns;
}
Рис. 17. Схема движения индексов при слиянии списков