mirror of
https://github.com/krahets/hello-algo.git
synced 2026-07-20 02:26:11 +00:00
deploy
This commit is contained in:
@@ -4379,14 +4379,14 @@
|
||||
|
||||
<!-- Page content -->
|
||||
<h1 id="92">9.2 Базовые операции графа<a class="headerlink" href="#92" title="Permanent link">¶</a></h1>
|
||||
<p>Базовые операции графа можно разделить на операции над "ребрами" и операции над "вершинами". При двух способах представления, "матрице смежности" и "списке смежности", реализация этих операций различается.</p>
|
||||
<p>Базовые операции графа можно разделить на операции над «ребрами» и операции над «вершинами». При двух способах представления, «матрице смежности» и «списке смежности», реализация этих операций различается.</p>
|
||||
<h2 id="921">9.2.1 Реализация на основе матрицы смежности<a class="headerlink" href="#921" title="Permanent link">¶</a></h2>
|
||||
<p>Пусть дан неориентированный граф с числом вершин <span class="arithmatex">\(n\)</span> . Тогда способы реализации различных операций показаны на рисунках ниже.</p>
|
||||
<p>Пусть дан неориентированный граф с числом вершин <span class="arithmatex">\(n\)</span> . Тогда способы реализации различных операций показаны на рисунке 9-7.</p>
|
||||
<ul>
|
||||
<li><strong>Добавление или удаление ребра</strong>: достаточно изменить соответствующее ребро в матрице смежности, что требует <span class="arithmatex">\(O(1)\)</span> времени. Поскольку граф неориентированный, необходимо одновременно обновить ребра в обоих направлениях.</li>
|
||||
<li><strong>Добавление вершины</strong>: в конец матрицы смежности добавляется строка и столбец, полностью заполненные нулями; это требует <span class="arithmatex">\(O(n)\)</span> времени.</li>
|
||||
<li><strong>Удаление вершины</strong>: из матрицы смежности удаляется строка и столбец. При удалении первой строки и первого столбца достигается худший случай, когда требуется "сдвинуть влево вверх" <span class="arithmatex">\((n-1)^2\)</span> элементов, поэтому используется <span class="arithmatex">\(O(n^2)\)</span> времени.</li>
|
||||
<li><strong>Инициализация</strong>: передаются <span class="arithmatex">\(n\)</span> вершин, затем инициализируется список вершин <code>vertices</code> длины <span class="arithmatex">\(n\)</span> , что требует <span class="arithmatex">\(O(n)\)</span> времени; после этого инициализируется матрица смежности <code>adjMat</code> размера <span class="arithmatex">\(n \times n\)</span> , что требует <span class="arithmatex">\(O(n^2)\)</span> времени.</li>
|
||||
<li><strong>Добавление вершины</strong>: в конец матрицы смежности добавляется строка и столбец, полностью заполненные нулями. Это требует <span class="arithmatex">\(O(n)\)</span> времени.</li>
|
||||
<li><strong>Удаление вершины</strong>: из матрицы смежности удаляется строка и столбец. При удалении первой строки и первого столбца достигается худший случай, когда требуется «сдвинуть влево вверх» <span class="arithmatex">\((n-1)^2\)</span> элементов, поэтому используется <span class="arithmatex">\(O(n^2)\)</span> времени.</li>
|
||||
<li><strong>Инициализация</strong>: передаются <span class="arithmatex">\(n\)</span> вершин, затем инициализируется список вершин <code>vertices</code> длины <span class="arithmatex">\(n\)</span> , что требует <span class="arithmatex">\(O(n)\)</span> времени. После этого инициализируется матрица смежности <code>adjMat</code> размера <span class="arithmatex">\(n \times n\)</span> , что требует <span class="arithmatex">\(O(n^2)\)</span> времени.</li>
|
||||
</ul>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="1:5"><input checked="checked" id="__tabbed_1_1" name="__tabbed_1" type="radio" /><input id="__tabbed_1_2" name="__tabbed_1" type="radio" /><input id="__tabbed_1_3" name="__tabbed_1" type="radio" /><input id="__tabbed_1_4" name="__tabbed_1" type="radio" /><input id="__tabbed_1_5" name="__tabbed_1" type="radio" /><div class="tabbed-labels"><label for="__tabbed_1_1"><1></label><label for="__tabbed_1_2"><2></label><label for="__tabbed_1_3"><3></label><label for="__tabbed_1_4"><4></label><label for="__tabbed_1_5"><5></label></div>
|
||||
<div class="tabbed-content">
|
||||
@@ -5566,13 +5566,13 @@
|
||||
<div style="margin-top: 5px;"><a href="https://pythontutor.com/iframe-embed.html#code=class%20GraphAdjMat%3A%0A%0A%20%20%20%20def%20__init__%28self%2C%20vertices%3A%20list%5Bint%5D%2C%20edges%3A%20list%5Blist%5Bint%5D%5D%29%3A%0A%20%20%20%20%20%20%20%20self.vertices%3A%20list%5Bint%5D%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20self.adj_mat%3A%20list%5Blist%5Bint%5D%5D%20%3D%20%5B%5D%0A%20%20%20%20%20%20%20%20for%20val%20in%20vertices%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.add_vertex%28val%29%0A%20%20%20%20%20%20%20%20for%20e%20in%20edges%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20self.add_edge%28e%5B0%5D%2C%20e%5B1%5D%29%0A%0A%20%20%20%20def%20size%28self%29%20-%3E%20int%3A%0A%20%20%20%20%20%20%20%20return%20len%28self.vertices%29%0A%0A%20%20%20%20def%20add_vertex%28self%2C%20val%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20n%20%3D%20self.size%28%29%0A%20%20%20%20%20%20%20%20self.vertices.append%28val%29%0A%20%20%20%20%20%20%20%20new_row%20%3D%20%5B0%5D%20%2A%20n%0A%20%20%20%20%20%20%20%20self.adj_mat.append%28new_row%29%0A%20%20%20%20%20%20%20%20for%20row%20in%20self.adj_mat%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20row.append%280%29%0A%0A%20%20%20%20def%20remove_vertex%28self%2C%20index%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20if%20index%20%3E%3D%20self.size%28%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28%29%0A%20%20%20%20%20%20%20%20self.vertices.pop%28index%29%0A%20%20%20%20%20%20%20%20self.adj_mat.pop%28index%29%0A%20%20%20%20%20%20%20%20for%20row%20in%20self.adj_mat%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20row.pop%28index%29%0A%0A%20%20%20%20def%20add_edge%28self%2C%20i%3A%20int%2C%20j%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20if%20i%20%3C%200%20or%20j%20%3C%200%20or%20i%20%3E%3D%20self.size%28%29%20or%20%28j%20%3E%3D%20self.size%28%29%29%20or%20%28i%20%3D%3D%20j%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28%29%0A%20%20%20%20%20%20%20%20self.adj_mat%5Bi%5D%5Bj%5D%20%3D%201%0A%20%20%20%20%20%20%20%20self.adj_mat%5Bj%5D%5Bi%5D%20%3D%201%0A%0A%20%20%20%20def%20remove_edge%28self%2C%20i%3A%20int%2C%20j%3A%20int%29%3A%0A%20%20%20%20%20%20%20%20if%20i%20%3C%200%20or%20j%20%3C%200%20or%20i%20%3E%3D%20self.size%28%29%20or%20%28j%20%3E%3D%20self.size%28%29%29%20or%20%28i%20%3D%3D%20j%29%3A%0A%20%20%20%20%20%20%20%20%20%20%20%20raise%20IndexError%28%29%0A%20%20%20%20%20%20%20%20self.adj_mat%5Bi%5D%5Bj%5D%20%3D%200%0A%20%20%20%20%20%20%20%20self.adj_mat%5Bj%5D%5Bi%5D%20%3D%200%0A%27Driver%20Code%27%0Aif%20__name__%20%3D%3D%20%27__main__%27%3A%0A%20%20%20%20vertices%20%3D%20%5B1%2C%203%2C%202%2C%205%2C%204%5D%0A%20%20%20%20edges%20%3D%20%5B%5B0%2C%201%5D%2C%20%5B0%2C%203%5D%2C%20%5B1%2C%202%5D%2C%20%5B2%2C%203%5D%2C%20%5B2%2C%204%5D%2C%20%5B3%2C%204%5D%5D%0A%20%20%20%20graph%20%3D%20GraphAdjMat%28vertices%2C%20edges%29%0A%20%20%20%20graph.add_edge%280%2C%202%29%0A%20%20%20%20graph.remove_edge%280%2C%201%29%0A%20%20%20%20graph.add_vertex%286%29%0A%20%20%20%20graph.remove_vertex%281%29&codeDivHeight=800&codeDivWidth=600&cumulative=false&curInstr=3&heapPrimitives=nevernest&origin=opt-frontend.js&py=311&rawInputLstJSON=%5B%5D&textReferences=false" target="_blank" rel="noopener noreferrer">Во весь экран ></a></div></p>
|
||||
</details>
|
||||
<h2 id="922">9.2.2 Реализация на основе списка смежности<a class="headerlink" href="#922" title="Permanent link">¶</a></h2>
|
||||
<p>Пусть неориентированный граф содержит в сумме <span class="arithmatex">\(n\)</span> вершин и <span class="arithmatex">\(m\)</span> ребер. Тогда различные операции можно реализовать способом, показанным на рисунках ниже.</p>
|
||||
<p>Пусть неориентированный граф содержит в сумме <span class="arithmatex">\(n\)</span> вершин и <span class="arithmatex">\(m\)</span> ребер. Тогда различные операции можно реализовать способом, показанным на рисунке 9-8.</p>
|
||||
<ul>
|
||||
<li><strong>Добавление ребра</strong>: достаточно добавить ребро в конец списка, соответствующего вершине; это требует <span class="arithmatex">\(O(1)\)</span> времени. Поскольку граф неориентированный, необходимо одновременно добавить ребра в обоих направлениях.</li>
|
||||
<li><strong>Удаление ребра</strong>: нужно найти и удалить указанное ребро в списке, соответствующем вершине; это требует <span class="arithmatex">\(O(m)\)</span> времени. В неориентированном графе необходимо удалить ребра в обоих направлениях.</li>
|
||||
<li><strong>Добавление вершины</strong>: в список смежности добавляется еще один список, а новая вершина становится его головным узлом; это требует <span class="arithmatex">\(O(1)\)</span> времени.</li>
|
||||
<li><strong>Удаление вершины</strong>: требуется пройти по всему списку смежности и удалить все ребра, содержащие указанную вершину; это требует <span class="arithmatex">\(O(n + m)\)</span> времени.</li>
|
||||
<li><strong>Инициализация</strong>: в списке смежности создаются <span class="arithmatex">\(n\)</span> вершин и <span class="arithmatex">\(2m\)</span> ребер; это требует <span class="arithmatex">\(O(n + m)\)</span> времени.</li>
|
||||
<li><strong>Добавление ребра</strong>: достаточно добавить ребро в конец списка, соответствующего вершине. Это требует <span class="arithmatex">\(O(1)\)</span> времени. Поскольку граф неориентированный, необходимо одновременно добавить ребра в обоих направлениях.</li>
|
||||
<li><strong>Удаление ребра</strong>: нужно найти и удалить указанное ребро в списке, соответствующем вершине. Это требует <span class="arithmatex">\(O(m)\)</span> времени. В неориентированном графе необходимо удалить ребра в обоих направлениях.</li>
|
||||
<li><strong>Добавление вершины</strong>: в список смежности добавляется еще один список, а новая вершина становится его головным узлом. Это требует <span class="arithmatex">\(O(1)\)</span> времени.</li>
|
||||
<li><strong>Удаление вершины</strong>: требуется пройти по всему списку смежности и удалить все ребра, содержащие указанную вершину. Это требует <span class="arithmatex">\(O(n + m)\)</span> времени.</li>
|
||||
<li><strong>Инициализация</strong>: в списке смежности создаются <span class="arithmatex">\(n\)</span> вершин и <span class="arithmatex">\(2m\)</span> ребер. Это требует <span class="arithmatex">\(O(n + m)\)</span> времени.</li>
|
||||
</ul>
|
||||
<div class="tabbed-set tabbed-alternate" data-tabs="3:5"><input checked="checked" id="__tabbed_3_1" name="__tabbed_3" type="radio" /><input id="__tabbed_3_2" name="__tabbed_3" type="radio" /><input id="__tabbed_3_3" name="__tabbed_3" type="radio" /><input id="__tabbed_3_4" name="__tabbed_3" type="radio" /><input id="__tabbed_3_5" name="__tabbed_3" type="radio" /><div class="tabbed-labels"><label for="__tabbed_3_1"><1></label><label for="__tabbed_3_2"><2></label><label for="__tabbed_3_3"><3></label><label for="__tabbed_3_4"><4></label><label for="__tabbed_3_5"><5></label></div>
|
||||
<div class="tabbed-content">
|
||||
@@ -5595,7 +5595,7 @@
|
||||
</div>
|
||||
<p align="center"> Рисунок 9-8 Инициализация списка смежности, добавление и удаление ребер и вершин </p>
|
||||
|
||||
<p>Ниже приведен код списка смежности. По сравнению с рисунками выше, реальная реализация имеет следующие отличия.</p>
|
||||
<p>Ниже приведен код списка смежности. По сравнению с тем, что показано на рисунке 9-8, реальная реализация имеет следующие отличия.</p>
|
||||
<ul>
|
||||
<li>Чтобы упростить добавление и удаление вершин, а также сделать код проще, мы используем список, то есть динамический массив, вместо связного списка.</li>
|
||||
<li>Для хранения списка смежности используется хеш-таблица, где <code>key</code> - это экземпляр вершины, а <code>value</code> - список смежных вершин данной вершины.</li>
|
||||
@@ -6757,7 +6757,7 @@
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
<p>Если смотреть только на таблицу, может показаться, что список смежности на основе хеш-таблицы является лучшим и по времени, и по памяти. Но на практике операции над ребрами в матрице смежности обычно выполняются быстрее, потому что там нужен лишь один доступ к массиву или одно присваивание. В целом матрица смежности воплощает принцип "обмена пространства на время", а список смежности - принцип "обмена времени на пространство".</p>
|
||||
<p>Если судить только по данным в таблице 9-2, может показаться, что список смежности на основе хеш-таблицы является лучшим и по времени, и по памяти. Но на практике операции над ребрами в матрице смежности обычно выполняются быстрее, потому что там нужен лишь один доступ к массиву или одно присваивание. В целом матрица смежности воплощает принцип «обмена пространства на время», а список смежности - принцип «обмена времени на пространство».</p>
|
||||
|
||||
<!-- Source file information -->
|
||||
|
||||
|
||||
Reference in New Issue
Block a user