Добавил:
Upload Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:
Методичка3.2.doc
Скачиваний:
37
Добавлен:
19.08.2019
Размер:
3.14 Mб
Скачать

Лабораторная работа № 6 структура данных граф

Цель работы: изучить структуру данных граф, разработать класс TGraph для работы с ней и получить практический навык его использования.

Теоретические сведения

Граф (Graph) ­– это структура данных, представленная в виде списка элементов, у каждого из которых может быть множество наследников и множество родителей.

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

Граф представляет собой совокупность вершин (Virteces) соединенных друг с другом ребрами (Edges).

Вершины графа обозначаются буквой V, а сам граф записывается в виде множества его вершин .

Ребра графа обозначаются буквой E, и записываются в виде объединения двух вершин ,

где - указывает начало ребра, - его конец.

Различают два графа:

  1. Направленные графы (орграф);

  2. Ненаправленные графы.

В направленных графах (directed graph или bigraph) существует направление ребра от начальной вершины до конечной вершины. Т.е.

В ненаправленных графах (undirected graph) ребра направлений не имеют. Т.е.

Направленный граф

Ненаправленный граф

Путем (Path) – называется объединение трех или более вершин, которые определяют способ прохода от до .

или

Путь из одной вершины в туже самую вершину называется циклом (Cycle).

или

Граф называется сильно связанным (strong connected), если для любой вершины существует путь или ребро для любой другой вершины.

Таким образом в сильно связанных графах существуют пути и .

Граф называется слабо связанным (light connected graph), если существует путь или ребро из одной вершины в любую другую. В слабо связанных графах из одной вершины можно добраться в любую другую, но обратного пути может и не существовать: или .

Strongly connected component – называется часть графа, которая сильно связана.

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

Существует два способа представления графа в памяти компбютера:

с помощью матрицы смежности;

с помощью связанного списка.

1. При представлении графа в виде матрицы смежности все вершины графа помещаются в одномерный список, к которому добавляется двумерная матрица квадратного вида. Пересечение строк и столбцов этой матрицы определяют вес ребра (weight edges). Если ребро существует, то его вес принимают равным 1, если не существует, то 0. Если ребра графа имеют другой вес, то вместо 1 указвается конкретный вес ребра.

Пример

A

B

C

D

A

0

1

1

0

B

0

0

1

1

C

0

0

0

0

D

0

0

1

0

Достоинства: простота хранения узлов.

Недостатки: в памяти необходимо хранить матрицу смежности даже при условии, что она заполнена не полностью.

2. При использовании связанного списка списка, к каждой вершине добавляется список связанных вершин с их весами.

Вершина

Список

Нет

Достоинства: вв памяти хранятся только те вершины, с которыми связаны данные, а не все вершины графа.

Недостатки: обращение к списку вершин происходит медленнее, чем непосредственная индексация.

Объявление класса TGraph

#include <vector>

using namespace std;

const int MaxSize=25;

template <class T>

class TGraph

{

private:

int GraphSize;

vector<T> Vertexes;

int Edge[MaxSize][MaxSize];

public:

TGraph();

int GetVertexPos(T &Vertex);

int GetWeight(T &Vertex1, T &Vertex2);

void InsertVertex(T &Vertex);

void InsertWeight(T &Vertex1, T &Vertex2, int Weight);

void DeleteVertex(T &Vertex);

void DeleteEdge(T &Vertex1, T &Vertex2);

};

В классе TGraph объявлено три закрытых поля. GraphSize – хранит текущий размер графа. Vertexes – список вершин графа, представленный в виде класса «вектор». Edge — двумерный массив, предназначенный для хранения матрицы смежности, максимальный размер которой определяется заданной константой MaxSize. В открытом разделе предусмотрены: конструктор, метод находящий порядковый номер заданой вершины в списке, метод возвращающий вес ребра между двумя вершинами, метод добавляющий новую вершину в граф, метод устанавливающий ребро между двумя вершинами с указанным весом, метод удаляющий узел графа и метод удаляющий ребро между двумя соответствующим вершинам.

Определение методов класса TGraph

Конструктор

template <class T>

TGraph<T>::TGraph()

{

for (int i=0; i<MaxSize; i++)

for (int j=0; j<MaxSize; j++)

Edge[i][j]=0;

GraphSize=0;

}

Все ребра в матрице смежности принимаются равными 0, и размер графа равен 0.

Поиск текущей позиции вершины

template <class T>

int TGraph<T>::GetVertexPos(T &Vertex)

{

int res=-1;

for (int i=0; i<GraphSize; i++)

if (Vertex[i]==Vertex)

{

res=i;

break;

}

return res;

}

Вначале просматривается весь список вершин и, если текущая вершина совпала с переменной, то возвращается ее позиция. В противном случае - (-1), т.е. Вершина не найдена.

Метод возвращающий вес между двумя вершинами

template <class T>

int TGraph<T>::GetWeight(T &Vertex1, T &Vertex2)

{

int pos1=GetVertexPos(Vertex1), pos2=GetVertexPos(Vertex2);

if (pos1!=-1 && pos2!=-1)

return Edge[pos1][pos2];

else

return 0;

}

Данный метод вначале ищет позиции двух передаваемых вершин. Если обе вершины найдены, то возвращается вес ребра, хранящийся в матрице смежности. В противном случае — 0, говорящий, что ребра нет.

Метод вставки узла

template <class T>

void TGraph<T>::InsertVertex(T &Vertex)

{

if (GraphSize==MaxSize)

throw Exception("Граф переполнен!");

int pos=GetVertexPos(Vertex);

if (pos==-1)

{

Vertex.push_back();

GraphSize++;

}

}

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

Метод задания веса ребра между двумя вершинами

template <class T>

void TGraph<T>::InsertWeight(T &Vertex1, T &Vertex2, int Weight)

{

int pos1=GetVertexPos(Vertex1), pos2=GetVertexPos(Vertex2);

if (pos1!=-1 && pos2!=-1)

Edge[pos1][pos2]=Weight;

else

throw Exception("Не найден узел!");

}

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

Метод удаления узла

template <class T>

void TGraph<T>::DeleteVertex(T &Vertex)

{

int pos=GetVertexPos(Vertex);

if (pos!=-1)

{

for (int i=pos+1; i<GraphSize; i++)

Vertexes[i-1]=Vertexes[i];

Vertexes.pop_back();

for (int i=pos+1; i<GraphSize; i++)

for (int j=0; j<pos; j++)

Edge[i-1][j]=Edge[i][j];

for (int i=0; i<pos; i++)

for (int j=pos+1; j<GraphSize; j++)

Edge[i][j-1]=Edge[i][j];

for (int i=pos+1; i<GraphSize; i++)

for (int j=pos+1; j<GraphSize; j++)

Edge[i-1][j-1]=Edge[i][j];

for (int i=0; i<GraphSize; i++)

{

Edge[i][GraphSize-1]=0;

Edge[GraphSize-1][i]=0;

}

}

}

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

В области I все строки перемещаются на одну позицию вверх, во II – области влево, в III — строки и столбцы вверх и влево.

  1. Метод удаления узла между двумя вершинами

template <class T>

void TGraph<T>::DeleteEdge(T &Vertex1, T &Vertex2)

{

int pos1=GetVertexPos(Vertex1), pos2=GetVertexPos(Vertex2);

if (pos1!=-1 && pos2!=-1)

Edge[pos1][pos2]=0;

else

throw Exception("Не найден узел!");

}