mirror of
https://github.com/krahets/hello-algo.git
synced 2026-08-09 10:30:59 +00:00
build
This commit is contained in:
@@ -4,30 +4,30 @@ comments: true
|
||||
|
||||
# 9.2 Базовые операции графа
|
||||
|
||||
Базовые операции графа можно разделить на операции над "ребрами" и операции над "вершинами". В двух способах представления - "матрица смежности" и "список смежности" - реализация будет различаться.
|
||||
Базовые операции графа можно разделить на операции над "ребрами" и операции над "вершинами". При двух способах представления, "матрице смежности" и "списке смежности", реализация этих операций различается.
|
||||
|
||||
## 9.2.1 Реализация на основе матрицы смежности
|
||||
|
||||
Пусть дан неориентированный граф с числом вершин $n$ . Тогда способы реализации различных операций показаны на рисунках ниже.
|
||||
|
||||
- **Добавление или удаление ребра**: достаточно изменить соответствующее ребро в матрице смежности, это требует $O(1)$ времени. Поскольку граф неориентированный, нужно одновременно обновлять ребра в обоих направлениях.
|
||||
- **Добавление вершины**: в конец матрицы смежности добавляется одна строка и один столбец, которые полностью заполняются нулями; это требует $O(n)$ времени.
|
||||
- **Удаление вершины**: из матрицы смежности удаляется одна строка и один столбец. В худшем случае, когда удаляются первая строка и первый столбец, приходится "сдвигать вверх-влево" $(n-1)^2$ элементов, поэтому требуется $O(n^2)$ времени.
|
||||
- **Добавление или удаление ребра**: достаточно изменить соответствующее ребро в матрице смежности, что требует $O(1)$ времени. Поскольку граф неориентированный, необходимо одновременно обновить ребра в обоих направлениях.
|
||||
- **Добавление вершины**: в конец матрицы смежности добавляется строка и столбец, полностью заполненные нулями; это требует $O(n)$ времени.
|
||||
- **Удаление вершины**: из матрицы смежности удаляется строка и столбец. При удалении первой строки и первого столбца достигается худший случай, когда требуется "сдвинуть влево вверх" $(n-1)^2$ элементов, поэтому используется $O(n^2)$ времени.
|
||||
- **Инициализация**: передаются $n$ вершин, затем инициализируется список вершин `vertices` длины $n$ , что требует $O(n)$ времени; после этого инициализируется матрица смежности `adjMat` размера $n \times n$ , что требует $O(n^2)$ времени.
|
||||
|
||||
=== "Инициализация матрицы смежности"
|
||||
=== "<1>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Добавление ребра"
|
||||
=== "<2>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Удаление ребра"
|
||||
=== "<3>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Добавление вершины"
|
||||
=== "<4>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Удаление вершины"
|
||||
=== "<5>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> Рисунок 9-7 Инициализация матрицы смежности, добавление и удаление ребер и вершин </p>
|
||||
@@ -1215,35 +1215,35 @@ comments: true
|
||||
|
||||
Пусть неориентированный граф содержит в сумме $n$ вершин и $m$ ребер. Тогда различные операции можно реализовать способом, показанным на рисунках ниже.
|
||||
|
||||
- **Добавление ребра**: достаточно добавить ребро в конец списка, соответствующего вершине; это требует $O(1)$ времени. Поскольку граф неориентированный, нужно одновременно добавлять ребра в обоих направлениях.
|
||||
- **Удаление ребра**: нужно найти и удалить указанное ребро в списке, соответствующем вершине; это требует $O(m)$ времени. В неориентированном графе нужно удалять ребра в обоих направлениях.
|
||||
- **Добавление ребра**: достаточно добавить ребро в конец списка, соответствующего вершине; это требует $O(1)$ времени. Поскольку граф неориентированный, необходимо одновременно добавить ребра в обоих направлениях.
|
||||
- **Удаление ребра**: нужно найти и удалить указанное ребро в списке, соответствующем вершине; это требует $O(m)$ времени. В неориентированном графе необходимо удалить ребра в обоих направлениях.
|
||||
- **Добавление вершины**: в список смежности добавляется еще один список, а новая вершина становится его головным узлом; это требует $O(1)$ времени.
|
||||
- **Удаление вершины**: требуется пройти по всему списку смежности и удалить все ребра, содержащие указанную вершину; это требует $O(n + m)$ времени.
|
||||
- **Инициализация**: в списке смежности создаются $n$ вершин и $2m$ ребер; это требует $O(n + m)$ времени.
|
||||
|
||||
=== "Инициализация списка смежности"
|
||||
=== "<1>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Добавление ребра"
|
||||
=== "<2>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Удаление ребра"
|
||||
=== "<3>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Добавление вершины"
|
||||
=== "<4>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
=== "Удаление вершины"
|
||||
=== "<5>"
|
||||
{ class="animation-figure" }
|
||||
|
||||
<p align="center"> Рисунок 9-8 Инициализация списка смежности, добавление и удаление ребер и вершин </p>
|
||||
|
||||
Ниже приведен код списка смежности. По сравнению с рисунками выше, реальная реализация имеет следующие отличия.
|
||||
|
||||
- Чтобы упростить добавление и удаление вершин, а также упростить код, мы используем список, то есть динамический массив, вместо связного списка.
|
||||
- Чтобы упростить добавление и удаление вершин, а также сделать код проще, мы используем список, то есть динамический массив, вместо связного списка.
|
||||
- Для хранения списка смежности используется хеш-таблица, где `key` - это экземпляр вершины, а `value` - список смежных вершин данной вершины.
|
||||
|
||||
Кроме того, в списке смежности мы используем класс `Vertex` для представления вершины. Причина в следующем: если, как и в матрице смежности, различать вершины по индексам списка, то при удалении вершины с индексом $i$ пришлось бы обходить весь список смежности и уменьшать на $1$ все индексы, большие $i$ , что крайне неэффективно. Если же каждая вершина является уникальным экземпляром `Vertex` , то после удаления одной вершины остальные вершины менять уже не требуется.
|
||||
Кроме того, в списке смежности используется класс `Vertex` для представления вершины. Причина в том, что если, как и в матрице смежности, различать вершины по индексам списка, то при удалении вершины с индексом $i$ пришлось бы обходить весь список смежности и уменьшать на $1$ все индексы, большие $i$ , что крайне неэффективно. Если же каждая вершина является уникальным экземпляром `Vertex` , то после удаления одной вершины остальные вершины менять уже не требуется.
|
||||
|
||||
=== "Python"
|
||||
|
||||
@@ -2371,7 +2371,7 @@ comments: true
|
||||
|
||||
## 9.2.3 Сравнение эффективности
|
||||
|
||||
Пусть в графе имеется $n$ вершин и $m$ ребер. В таблице 9-2 сравниваются временная и пространственная эффективность матрицы смежности и списка смежности. Обрати внимание: список смежности (связный список) соответствует реализации из этой статьи, а список смежности (хеш-таблица) означает вариант, где все списки заменены хеш-таблицами.
|
||||
Пусть в графе имеется $n$ вершин и $m$ ребер. В таблице 9-2 сравниваются временная и пространственная эффективность матрицы смежности и списка смежности. Обратите внимание: список смежности (связный список) соответствует реализации из этой статьи, а список смежности (хеш-таблица) означает вариант, в котором все списки заменены хеш-таблицами.
|
||||
|
||||
<p align="center"> Таблица 9-2 Сравнение матрицы смежности и списка смежности </p>
|
||||
|
||||
@@ -2388,4 +2388,4 @@ comments: true
|
||||
|
||||
</div>
|
||||
|
||||
Если смотреть только на таблицу, может показаться, что список смежности на основе хеш-таблицы является лучшим и по времени, и по памяти. Но на практике операции над ребрами в матрице смежности часто выполняются быстрее, потому что там нужен лишь один доступ к массиву или одно присваивание. В целом матрица смежности воплощает принцип "обмен пространства на время", а список смежности - принцип "обмен времени на пространство".
|
||||
Если смотреть только на таблицу, может показаться, что список смежности на основе хеш-таблицы является лучшим и по времени, и по памяти. Но на практике операции над ребрами в матрице смежности обычно выполняются быстрее, потому что там нужен лишь один доступ к массиву или одно присваивание. В целом матрица смежности воплощает принцип "обмена пространства на время", а список смежности - принцип "обмена времени на пространство".
|
||||
|
||||
Reference in New Issue
Block a user