Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Алгоритмы и структ дан.docx
Скачиваний:
0
Добавлен:
01.05.2025
Размер:
233.51 Кб
Скачать

16, 4, 93, 47, 14, 66, 255, 13, 4, 31, 552, 41, 74, 39. Идеально-сбалансированное,поисковое, avl.

Сильно-ветвящиеся В деревья.

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

Обозначим через n порядок дерева. m - число элементов на странице. В таких обозначениях B дерево порядка n называется структура, обладающая следующими свойствами: 1. Каждая страница содержит число элементов не более m<=2n. 2. Каждая страница за исключением корневой, содержит не менее m>=n элементов. N<=m<=2n. 3. Каждая страница либо является листом (не имеет потомков), либо имеет m+1 потомков. 4. Все страницы листья находятся на одном уровне.

Включение B дерева происходит за один шаг, если у нас m<2n и за 3 шага, если m=2n. 1 шаг: проверяете, есть ли ключ в дереве. Если его нет, происходит включение. Проверяется, если страница c заполнена, и включение в неё невозможно, то переходим к шагу 2. Ы. 2 шаг: если страница c разделяется на две страницы c и d. 3 шаг: ключи, их в этот момент 2n+1 поровну распределяются между страницами c и d, а средний по значению ключ переносится на один уровень вверх на родительскую страницу.

Пример 1. (он ужасен и расположен в тетради…)

Графы и алгоритмы на графах.

ГрррРРррафы! Являются обобщенными иерархическими структурами. G=<V,E> V- множество вершин, E – ребра или дуги.

Способы машинного представления графа.

Рассмотрим несколько способов представления графов с оценкой их достоинств и недостатков. 1. Классическим способом представления графов служит матрица инциденции. Эта матрица Aij размера nxm где n - число строк, соответствующие вершинам, m – число столбцов, которое равно числу ребер. В случае неориентированного графа, столбец, соответствующий ребру [Vi, Vj] содержит единиицу в строках соответствующих вершине Vi, так и в строке Vj и нули в остальных строках. Для ориентированного графа столбец соответствующий дуге <Vi, Vj> содержит

-1 в строке соответствующей Vi и 1 в строке соответствующей вершине Vj и нули во всех остальных строках.

1,2

1,4

2,3

2,4

3,4

1

-1

-1

0

0

0

2

1

0

-1

1

0

3

0

0

1

0

1

4

0

1

0

-1

-1

С алгоритмической точки зрения, матрица инциденции является самым худшим способом представления графа, т.к.:1. Требует m*n ячеек памяти, большинство из которых заполнены нулями. 2. Неудобен доступ к информации, т.к. определение «существует ли дуга Vi Vj» требует в худшем случае перебора всех столбцов матрицы=> m шагов.

2 способ – матрица смежности. Также определим её как Aij=1, если существует ребро ij и Aij = 0, если такого ребра не существует. Причем для неориентированного графа (ij)=(ji).

1

2

3

4

1

0

1

0

1

2

0

0

1

0

3

0

0

0

0

4

0

1

1

0

Недостаток – независимо от числа ребер, объем заданной памяти n*n=n2.

3 способ

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

1

1

2

4

4

2

4

3

2

3

Списки инцидентности.

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

1

•→

2

•→

4

NULL

2

•→

3

NULL

3

NULL

4

•→

2

•→

3

NULL

Способы прохождения графов.

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

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

Пусть имеется стек S для хранения смежных вершин и список L для хранения обработанных вершин.

  1. Поместим начальную вершину в стек.

  2. Начинаем итерационный процесс, выталкиваем вершины из стека и её обработки. На каждой итерации используется следующая стратегия: 2.1 Вытолкнуть вершину V из стека S. 2.2 Проверить по списку L была ли она обработана (есть ли она в списке L). Если нет, провести обработку этой вершины, включив её в список L, чтобы избежать повторной обработки, а также поместить в стек те смежные с V вершины, которых еще нет в списке L. Процесс завершается, когда стек становится пустым. На этот момент список L содержит список посещенных или обработанных вершин.

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

При поиске в ширину, начиная с некоторой начальной вершины, производится обработка каждой смежной с ней вершиной. Затем сканирование продолжается на следующем уровне смежных вершин и так до конца пути. При этом для запоминания смежных вершин используется очередь, т.е. поиск в ширину основывается на замене стека очередью (Чем раньше посещается вершина, тем раньше она используется, т.е. удаляется из очереди). Использование вершины происходит с помощью просмотра сразу всех еще не рассмотренных соседей этой вершины и её занесении в результирующий список. Och - очередь для промежуточного хранения. L - для хранения результата списка.

Начальная вершина заносится в очередь. Далее начинается итерационный процесс на каждом шаге которого выполняются следующие действия: 2.1 Удалить вершину V из очереди 2.2. проверить её наличие в списке обработанных вершин. проверить её в списке… вершин. Если вершины V нет в списке L - включить её в этот список 2.3. одновременно получить все смежные с V вершины и вставить в очередь те из них, которые отсутствуют в L. Итерационный процесс продолжается до тех пор, пока очередь не опустеет.

Рисунок

Оба вида поиска в графе могут быть использованы: 1. Для нахождения остового дерева 2. Для нахождения пути между фиксированными вершинами V и U достаточно начать поиск в графе с вершиной V и вести его до момента посещения вершины U.

Анализ сложности поиска в ширину и в длину. Пусть граф задан матрицей смежности. Тогда посещение каждой вершины требует времени вычислений O(n). При добавлении в список обработанных вершин, проверяется её наличие в этом результирующем списке L. Иначе кол-во шагов O(n).

O(1) s<=V

While O(n)

V<=S

O(n)

O(1)<=N

O(n)

Эйлеров граф. Эйлеров путь. Эйлеро цикл. Алгоритм нахождения эйлерова цикла.

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

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

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

Алгоритм нахождения эйлерова цикла в графе.

Пусть дан граф G=<V,E> который является связным, и все вершины которого имеют четную степень. Граф представлен списками инцидентности rec[V]. Для промежуточного хранения используется временный стек STEC. А для хранения результата используется CE.

  1. STEC=NULL; CE=NULL;

  2. V=V0 произвольная начальная вершина.

  3. STEC<=V; - занесение V0 в STEC.

  4. While (STEC != NULL) do

  5. V = TOP (STEC); - получить значение элемента вершины стека.

  6. If (rec[V] !=NULL)

  7. U = V1; - первый элемент в списке rec[V];

  8. STEC<=U;

  9. Rec[V]=rec[V]-U; rec[U]=rec[U]-V; удаление ребра [V,U]

  10. V=U; end

  11. Else V<=STEC; CE<=V; - если rec[V]=NULL

Принципы действия алгоритма можно объяснить след образом: пусть V0 – вершина выбранная в строке 2. Цикл while это строка 4 начинает строить путь сначала в V0, Причем вершины этого пути помещаются в промежуточный стек, а ребра удаляются из графа. Эти действия продолжаются до момента, когда путь нельзя удлинить, включив в него новую вершину. В этот момент, когда путь нельзя удлинить, должно быть V=V0. На этот момент из нашего графа удален цикл C1 и вершины этого цикла находятся в промежуточном стеке STEС. Если в граф C1 вошли все ребра графа, то C1 является эйлеровым циклом. Если в цикл C1 вошли не все ребра графа, то в оставшемся графе степень произвольной вершины останется четной. Вершина V=V0 переносится из промежуточного стека в результирующий и процесс продолжается с очередной вершины V , которая является верхним элементом промежуточного стека. Эти действия продолжаются до момента, когда промежуточный стек не опустеет. По окончании алгоритма, результирующий стек содержит эйлеров цикл. Сложность этого алгоритма в худшем O(n2)

Нахождения кратчайшего пути. Алгоритм Дейстры.

С помощью алгоритма в 1955 году можно найти кратчайшее расстояние с помощью между двумя вершина S и T или от выделенной S до всех остальных при условии положительной длины ребер (дуг). В алгоритме Дейстры выделяются две части.

  1. Отыскание длины кратчайшего пути методом расстановки меток и отыскания последовательности вершин соответствующих путей. В процессе работы алгоритма вершинам графа присваиваются метки, которые подразделяются на временные и постоянные. Временная метка – d(x) обозначает, что до вершины x еще не найдено кратчайшее расстояние, и d(y) – постоянная метка, которая присваивается вершине y до которой на текущем шаге найдено кратчайшее расстояние. Причем d(y)=min{d(x)}. Далее, чтобы использовать алгоритм, преобразуется и представление графа. Пусть граф задан матрицей смежности, в которой aij= d(I,j), если существует ребро (i,j), и aij = бесконечности, если (i,j) не существует. A(i,i)=0. Перед началом работы алгоритма, всем вершинам присваивают метки d(x) = бесконечность.

Основные шаги работы алгоритма:

  1. Пусть s – некоторая начальная вершина. Присваиваем S постоянную метку y=S; d(y)=d(S)=0. D(x) = бесконечность.

  2. Для всех вершин X, смежных с у, и не получивших постоянную метку, пересчитываем расстояние d(x) по формуле d(x)=min{d(x),d(y)+a(y,x)}

  1. Если все d(x) = бесконечности, то вершина изолирована. – закончить процедуру алгоритма, т.к. в исходном графе отсутствуют пути из S в остальные вершины. В противном случае, если не все d(x)= беск, выбрать ту из вершин X, которая имеет наименьшую временную метку.

  2. Если y = t, то закончить процедуру, т.к. кратчайший путь из S в T найден, иначе шаг 2. Простое изменение этого алгоритма позволяет получить кратчайшие пути от S ко всем остальным вершинам графа. Для этого достаточно изменить правило остановки процедуры. Останавливаться не при y=t, а в случае, когда все вершины получать постоянные метки. Трудоемкость алгоритма при этом не возрастет, т.к. вершина T в само худшем случае получает постоянную метку самой последней. Сложность алгоритма O(n^2).

Вторая часть. С помощью этих шагов можно найти расстояние между вершинами, а не сам путь. Однако, зная расстояние, и при условии положительной длины всех контуров, легко найти и сами кратчайшие пути. Для этого достаточно отметить, что для любых двух вершин S,T: S!=T существует некоторая вершина V: d(S,T)= d(S,V)+d(V,T)

Таким свойством обладает предпоследняя вершина кратчайшего пути из S в T. Далее мы можем найти такую вершину U, для которой d(S,V)=d(S,U)+d(U,V)

Рассмотрим вариант алгоритма, другой, реализация алгоритма Дейстры. Алгоритм использует три массива размерностью n каждый (число вершин). A[] содержит две метки: 0 - вершина не получила постоянную метку, 1 – получила. Второй массив B содержит текущее кратчайшее расстояние от S до соответствующей вершины. И третий массив C содержит номера предпоследних вершин на текущем кратчайшем пути из S в T.

1 Шаг. В цикле от 1 до n мы заполняем нулями массив A. i – начальный номер вершины, тогда a[i]=1, C[i]=0, и в массив B переносим i строку матрицы B.

2 Шаг. Найти минимум в массиве B среди тех элементов k, для которых a[k]=0. Т.е. пусть минимум достигается на индексе j, т.е. B[j]<=B[k]+d[j][k], то a[j][k], следовательно присваиваем b[k]=b[j]+d[j][k]. (while Пока a[T]=1 либо пока все a[i]=1) – этот цикл на весь шаг 2.

3 Шаг. Нахождение самого пути. Путь от S до T подается в обратном порядке, в следующей процедуре. 3.1.Напечатать T. 3.2 z=C[T]. 3.3. напечатать z перед T. 3.4. Переменной Z присвоить c[z]. Проверить если c[z]=0, то конец. Иначе перейти к 3.3.