# Граф Граф (graph) - это нелинейная структура данных, состоящая из вершин (vertex) и ребер (edge). Мы можем абстрактно представить граф $G$ как множество вершин $V$ и множество ребер $E$ . В примере ниже показан граф, содержащий 5 вершин и 7 ребер. $$ \begin{aligned} V & = \{ 1, 2, 3, 4, 5 \} \newline E & = \{ (1,2), (1,3), (1,5), (2,3), (2,4), (2,5), (4,5) \} \newline G & = \{ V, E \} \newline \end{aligned} $$ Если рассматривать вершины как узлы, а ребра как ссылки (указатели), соединяющие эти узлы, то граф можно считать структурой данных, выросшей из связного списка. Как показано на рисунке ниже, **по сравнению с линейными отношениями (связный список) и отношениями разделения (дерево), сетевые отношения (граф) обладают большей свободой** , а потому и сложнее. ![Связь между связным списком, деревом и графом](graph.assets/linkedlist_tree_graph.png) ## Распространенные типы и термины графов В зависимости от того, имеют ли ребра направление, графы делятся на неориентированные графы (undirected graph) и ориентированные графы (directed graph) , как показано на рисунке ниже. - В неориентированном графе ребро означает "двустороннюю" связь между двумя вершинами, например отношение "друзья" в WeChat или QQ. - В ориентированном графе ребро имеет направление, то есть ребра $A \rightarrow B$ и $A \leftarrow B$ независимы друг от друга, как, например, отношения "подписка" и "подписчик" в Weibo или Douyin. ![Ориентированный и неориентированный графы](graph.assets/directed_graph.png) В зависимости от того, достижимы ли все вершины друг из друга, граф делится на связный граф (connected graph) и несвязный граф (disconnected graph) , как показано на рисунке ниже. - В связном графе, начиная из некоторой вершины, можно добраться до любой другой вершины. - В несвязном графе, начиная из некоторой вершины, по крайней мере одна вершина оказывается недостижимой. ![Связный и несвязный графы](graph.assets/connected_graph.png) Мы также можем добавить к ребрам переменную "вес" и тем самым получить взвешенный граф (weighted graph) , показанный на рисунке ниже. Например, в мобильных играх вроде Honor of Kings система может вычислять "степень близости" между игроками по времени, проведенному в совместных играх; такую сеть близости можно описать взвешенным графом. ![Взвешенный и невзвешенный графы](graph.assets/weighted_graph.png) Для структуры данных "граф" используются следующие распространенные термины. - Смежность (adjacency): если между двумя вершинами существует ребро, то эти вершины называются "смежными". На рисунке выше вершинам 2, 3, 5 смежна вершина 1. - Путь (path): последовательность ребер, ведущая из вершины A в вершину B, называется "путем" от A до B. На рисунке выше последовательность ребер 1-5-2-4 представляет один из путей от вершины 1 к вершине 4. - Степень (degree): число ребер, принадлежащих вершине. Для ориентированного графа входящая степень (in-degree) показывает число ребер, ведущих в вершину, а исходящая степень (out-degree) показывает число ребер, исходящих из вершины. ## Представление графа Распространенные способы представления графа включают "матрицу смежности" и "список смежности". Ниже в качестве примера используется неориентированный граф. ### Матрица смежности Пусть число вершин графа равно $n$ ; тогда матрица смежности (adjacency matrix) использует матрицу размера $n \times n$ для представления графа: каждая строка и каждый столбец соответствуют вершине, а элементы матрицы отражают наличие ребра, то есть показывают, существует между двумя вершинами связь или нет. Как показано на рисунке ниже, пусть матрица смежности обозначается как $M$ , а список вершин - как $V$ ; тогда элемент матрицы $M[i, j] = 1$ означает, что между вершинами $V[i]$ и $V[j]$ существует ребро, а элемент $M[i, j] = 0$ означает, что ребра между ними нет. ![Представление графа матрицей смежности](graph.assets/adjacency_matrix.png) Матрица смежности обладает следующими особенностями. - В простом графе вершина не может соединяться сама с собой, поэтому элементы на главной диагонали матрицы смежности не имеют смысла. - Для неориентированного графа ребра в двух направлениях эквивалентны, поэтому матрица смежности симметрична относительно главной диагонали. - Если заменить в матрице смежности значения $1$ и $0$ на веса, то можно представить и взвешенный граф. При представлении графа матрицей смежности мы можем напрямую обращаться к элементам матрицы, чтобы получить информацию о ребрах, поэтому операции добавления, удаления, поиска и изменения обладают высокой эффективностью, равной $O(1)$ . Однако пространственная сложность матрицы равна $O(n^2)$ , поэтому она занимает заметный объем памяти. ### Список смежности Список смежности (adjacency list) использует $n$ связанных списков для представления графа, где узлы списка обозначают вершины. $i$-й список соответствует вершине $i$ и хранит все вершины, смежные с ней, то есть все вершины, соединенные с этой вершиной. На рисунке ниже показан пример графа, представленного списком смежности. ![Представление графа списком смежности](graph.assets/adjacency_list.png) Список смежности хранит только реально существующие ребра, а общее число ребер обычно значительно меньше $n^2$ , поэтому этот способ существенно экономит пространство. Однако для поиска ребра в списке смежности нужно проходить по списку, поэтому по времени он уступает матрице смежности. Если посмотреть на рисунок выше, можно заметить, что **структура списка смежности очень похожа на "метод цепочек" в хеш-таблице, поэтому для оптимизации эффективности здесь можно использовать сходные идеи**. Например, когда список становится слишком длинным, его можно преобразовать в AVL-дерево или красно-черное дерево, чтобы улучшить временную сложность с $O(n)$ до $O(\log n)$ ; можно также превратить его в хеш-таблицу и снизить сложность до $O(1)$ . ## Типичные применения графов Как показано в таблице ниже, многие реальные системы можно моделировать графами, а соответствующие задачи затем сводить к задачам вычислений на графах.

Таблица   Распространенные графы в реальной жизни

| | Вершина | Ребро | Задача вычислений на графе | | -------- | ------- | -------------------- | -------------------------- | | Социальные сети | Пользователь | Дружеская связь | Рекомендация потенциальных друзей | | Линии метро | Станция | Связность между станциями | Рекомендация кратчайшего маршрута | | Солнечная система | Небесное тело | Гравитационное взаимодействие между телами | Вычисление орбит планет |