图 : 是一种线性结构,由顶点集合(vertex)及顶点间的关系集合组成的一种数据结构。
图的存储:
临接矩阵:将所有的顶点的信息组织成一个顶点表,然后利用矩阵来表示各顶点之间的临接关系,称为临接矩阵。
邻接表:使用数组存储顶点集合,使用链表链接边的关系。
图的邻接矩阵存储实现代码:
#pragma once
#include<assert.h>
template<class V, class W>
class GraphMatrix
{
public:
GraphMatrix(const V* vArray, int size, bool IsDigraph = false)
:_vArray(new V[size])
, _vSize(size)
, IsDigraph(IsDigraph)
{
_Matrix = new W*[_vSize];
for (int i = 0; i < size; ++i)
{
_vArray[i] = vArray[i];
_Matrix[i] = new W[_vSize];
memset(_Matrix[i], 0, sizeof(W)*_vSize);
}
}
int GetVertexIndex(const V& vt)
{
for (int i = 0; i < _vSize; ++i)
{
if (_vArray[i] == vt)
{
return i;
}
}
return -1;
}
void AddEdge(const V& src, const V& dst, const W& weight)
{
int srcIndex = GetVertexIndex(src);
int dstIndex = GetVertexIndex(dst);
assert(srcIndex != -1);
assert(dstIndex != -1);
if (IsDigraph)
{
_Matrix[srcIndex][dstIndex] = weight;
}
else
{
_Matrix[srcIndex][dstIndex] = weight;
_Matrix[dstIndex][srcIndex] = weight;
}
}
void Display()
{
for (int i = 0; i < _vSize; ++i)
{
cout << _vArray[i] << " ";
}
cout << endl;
for (int i = 0; i < _vSize; ++i)
{
for (int j = 0; j < _vSize; ++j)
{
cout << _Matrix[i][j] << " ";
}
cout << endl;
}
cout << endl;
}
~GraphMatrix()
{
if (_vArray != NULL)
{
delete[] _vArray;
_vArray = NULL;
for (int i = 0; i < _vSize; ++i)
{
delete[] _Matrix[i];
_Matrix[i] = NULL;
}
delete[] _Matrix;
_Matrix = NULL;
}
}
private:
V* _vArray; //顶点集
int _vSize; //顶点数
W** _Matrix; //邻接矩阵
bool IsDigraph;
};
测试用例:
void TestGraphMatrix1()
{
GraphMatrix<char, int> gm("ABCDE", 5);
gm.AddEdge('A', 'D', 10);
gm.AddEdge('A', 'E', 20);
gm.AddEdge('B', 'C', 10);
gm.AddEdge('B', 'D', 20);
gm.AddEdge('B', 'E', 30);
gm.AddEdge('C', 'E', 40);
gm.Display();
}
//有向图
void TestGraphMatrix2()
{
GraphMatrix<char, int> gm("ABCDE", 5, true);
gm.AddEdge('A', 'D', 10);
gm.AddEdge('E', 'A', 20);
gm.AddEdge('B', 'C', 10);
gm.AddEdge('D', 'B', 20);
gm.AddEdge('E', 'B', 30);
gm.AddEdge('C', 'E', 40);
gm.Display();
}
图的邻接表存储实现代码:
#pragma once
template<class V, class W>
struct LinkEdge
{
W _w;
size_t _srcIndex;
size_t _dstIndex;
LinkEdge<V, W>* _next;
LinkEdge(size_t srcIndex, size_t dstIndex, const W& w)
: _w(w)
, _srcIndex(srcIndex)
, _dstIndex(dstIndex)
, _next(NULL)
{}
};
template<class V, class W>
struct LinkVertex
{
V _vertex;
LinkEdge<V, W>* _head;
LinkVertex(const V& vertex = V())
:_vertex(vertex)
, _head(NULL)
{}
};
template<class V, class W>
class GraphLink
{
public:
GraphLink(const V* vArray, int size, bool IsDigraph = false)
:_vSize(size)
, _IsDigraph(IsDigraph)
{
_LinkTable = new LinkVertex<V, W>[size];
for (int i = 0; i < size; i++)
{
_LinkTable[i]._vertex = vArray[i];
}
}
public:
void AddEdge(const V& src, const V& dst, const W& weight)
{
int srcIndex = GetVertexIndex(src);
int dstIndex = GetVertexIndex(dst);
assert(srcIndex != -1);
assert(dstIndex != -1);
if (_IsDigraph)
{
_AddEdge(srcIndex, dstIndex, weight);
}
else
{
_AddEdge(srcIndex, dstIndex, weight);
_AddEdge(dstIndex, srcIndex, weight);
}
}
void Display()
{
for (int i = 0; i < _vSize; i++)
{
cout << _LinkTable[i]._vertex << "[" << i << "]->";
LinkEdge<V, W>* cur = _LinkTable[i]._head;
while (cur != NULL)
{
cout << cur->_w << "[" << cur->_dstIndex << "]->";
cur = cur->_next;
}
cout << "NULL" << endl;
}
cout << endl;
}
protected:
int GetVertexIndex(const V& vertex)
{
for (int i = 0; i < _vSize; i++)
{
if (_LinkTable[i]._vertex == vertex)
{
return i;
}
}
return -1;
}
void _AddEdge(const V& srcIndex, const V& dstIndex, const W& weight)
{
LinkEdge<V, W>* head = _LinkTable[srcIndex]._head;
LinkEdge<V, W>* tmp = new LinkEdge<V, W>(srcIndex, dstIndex, weight);
tmp->_next = head;
_LinkTable[srcIndex]._head = tmp;
}
private:
LinkVertex<V, W>* _LinkTable;
int _vSize;
bool _IsDigraph;
};
测试用例:
//无向图
void TestGraphLink1()
{
GraphLink<char, int> gl("ABCDE", 5);
gl.AddEdge('A', 'D', 10);
gl.AddEdge('A', 'E', 20);
gl.AddEdge('B', 'C', 10);
gl.AddEdge('B', 'D', 20);
gl.AddEdge('B', 'E', 30);
gl.AddEdge('C', 'E', 40);
gl.Display();
}
//有向图
void TestGraphLink2()
{
GraphLink<char, int> gl("ABCDE", 5, true);
gl.AddEdge('A', 'D', 10);
gl.AddEdge('E', 'A', 20);
gl.AddEdge('B', 'C', 10);
gl.AddEdge('D', 'B', 20);
gl.AddEdge('E', 'B', 30);
gl.AddEdge('C', 'E', 40);
gl.Display();
}