Shaykhutdinov-T-I's blog

By Shaykhutdinov-T-I, 12 years ago, In Russian

Наткнулся на пост, решил помочь. При написании комментария возникали вопросы о том или ином изложении материала, чтобы возникающие от недосказанности вопросы не засоряли тему решил написать тут. Далее будет рассмотрен один их возможных вариантов реализации этой структуры данных на языке PASCAL. Сопутствующие определения, понятия советую смотреть на http://ru.wikipedia.org/wiki/Граф_(математика).

Итак начнем с ориентированных не взвешенных графов. Для каждой вершины сопоставим список исходящих ребер, они будут характеризоваться вершинами, куда они ведут (Value[e]). Так как изначально неизвестно (как правило) ни количество вершин, ни количество ребер для каждой, а лишь даны ограничения по общему количеству вершин и количеству ребер, то списки будут храниться в одном массиве Value[1..Emax] (value[i] = u — итое ребро ведет в вершину u). Для организации списков на нем нужны будут указатели на следующие элементы списка. Для не динамической реализации указателями послужат индексы следующих элементов. Для начал списков заведем массив Head[1..Vmax] (head[i] — содержит индекс начала итого списка в массиве value). Для переходов по элементам списка заведем массив Next[1..Emax] (next[i] — показывает следующий элемент списка после i — го). Объявим список:

Const
  Emax = 200000; // - максимальное число ребер
  Vmax = 100000; // - максимальное число вершин

Var
  head: array [1..Vmax] of integer; // - индексы начал списков
  next: array [1..Emax] of integer; // - индексы следующих элементов списков
  value: array [1..Emax] of integer; // - значения элементов списков
  nf: integer; // - следующая свободная позиция изначально установить 1.

Изначально все элементы списка объявлены 0. Для добавления ребра напишем процедуру Add(v, u), которая добавит в список ребер, исходящих из вершины v, ребро (v->u).

procedure Add(v, u: integer); //ребро (v->u)
begin
  next[nf] := head[v]; //в свободную ячейку следующим элементом делаем начало списка вершины V
  Value[nf] := u; //в эту ячейку записываем информацию о ребре (у нас конец ребра)
  head[v] := nf; //устанавливаем новое начало списка вершин V
  inc(nf); //увеличиваем значение свободной ячейки.
end;

Для того, чтобы пробежаться по ребрам, исходящим из вершины V

Procedure GoV(v: integer); //рёбрa (v->)
var
  u, i: integer; //вспомогательные переменные, где i - индекс в списках, u - конец ребра
begin
  i := head[v]; //устанавливаем на начало списка  
  while i <> 0 do //пока не покажет на конец списка
    begin 
      u := value[i];
      ...
      i := next[i];
    end;
end;

Реализации для других графов опишу как модификации при надобности. На всякий случай можете почитать еще статьи в интернете (например 1, 2, 3, ну и самое хорошее объяснение 4 от andrewzta)

  • Vote: I like it
  • +30
  • Vote: I do not like it