图的基本概念
图是由顶点集合及顶点间的关系组成的一种数据结构:G = (V, E)
V是一个非空有穷集,称作顶点集,其元素称作顶点或结点.
E = {(x,y)|x,y属于V}或者E = {<x, y>|x,y属于V && Path(x, y)
是顶点间关系的有穷集合,也叫做边的集合。
有向图和无向图:在有向图中,顶点对<x, y>是有序的,顶点对<x,y>称为顶点x到顶点y的一条
边(弧),<x, y>和<y, x>是两条不同的边,比如下图G3和G4为有向图。在无向图中,顶点对(x, y)
是无序的,顶点对(x,y)称为顶点x和顶点y相关联的一条边,这条边没有特定方向,(x, y)和(y,x)
是同一条边,比如下图G1和G2为无向图。注意:无向边(x, y)等于有向边<x, y>和<y, x>。
图的存储结构
1.邻接矩阵
template<class W>
struct Edge
{
Edge(int srci,int dsti,W w)
:_srci(srci)
,_dsti(dsti)
,_w(w)
{}
bool operator>(const Edge& e) const
{
return _w > e._w;
}
int _srci;
int _dsti;
W _w;
};
template<class V,class W ,W MAX_W = INT_MAX,bool direction = false>
class Graph
{
public:
typedef Graph<V, W, MAX_W, direction> self;
typedef Edge<W> Edge;
Graph(const V* vertexs, size_t n)
:_vertexs(n)
, _matrix(n, vector<W>(n, MAX_W))
{
for (int i = 0; i < n; ++i)
{
_vertexs[i] = vertexs[i];
}
for (int i = 0; i < n; ++i)
{
_mapIndex[_vertexs[i]] = i;
}
}
int findIndex(const V& vertex)
{
auto it = _mapIndex.find(vertex);
if (it == _mapIndex.end())
{
cout << "没找到" << endl;
return -1;
}
//找到了
return it->second;
}
bool AddEdge(const V& src,const V& dst,W w)
{
int srci = findIndex(src);
int dsti = findIndex(dst);
if (srci == dsti)
{
return false;
}
_matrix[srci][dsti] = w;
//无向图
if (direction == false)
{
_matrix[dsti][srci] = w;
}
return true;
}
void print()
{
int n = _vertexs.size();
for (int i = 0; i < n; i++)
{
cout << _vertexs[i] << "->" << '[' << i << ']' << endl;
}
cout << endl;
for (int i = 0; i < n; i++)
{
for (int j = 0; j < n; ++j)
{
if (_matrix[i][j] == MAX_W)
{
cout <<"* ";
}
else
{
cout << _matrix[i][j]<<" ";
}
}
cout << endl;
}
}
private:
vector<V> _vertexs; // 所有点的集合
map<V, int> _mapIndex; // 找点的下标
vector<vector<W>> _matrix; // 领接矩阵
};
void test()
{
Graph<char, int, INT_MAX, true> g("0123", 4);
g.AddEdge('0', '1', 1);
g.AddEdge('0', '3', 4);
g.AddEdge('1', '3', 2);
g.AddEdge('1', '2', 9);
g.AddEdge('2', '3', 8);
g.AddEdge('2', '1', 5);
g.AddEdge('2', '0', 3);
g.AddEdge('3', '2', 6);
g.print();
}
2.邻接表
无向图邻接表存储
有向图邻接表存储
template<class W>
struct Edge
{
Edge(int srci,int dsti,W w)
:_srci(srci)
,_dsti(dsti)
,_w(w)
,_next(nullptr)
{}
int _srci;//起点
int _dsti;//终点
W _w; //权值
Edge<W>* _next;
};
template<class V, class W, W MAX_W = INT_MAX, bool direction = false>
class Graph
{
public:
typedef Edge<W> Edge;
Graph(const vector<V>& vertexs, size_t n)
:_vertexs(n)
, _chart(n, nullptr)
{
for (int i = 0; i < n; ++i)
{
_vertexs[i] = vertexs[i];
}
for (int i = 0; i < n; ++i)
{
_mapIndex[_vertexs[i]] = i;
}
}
Graph(const V* vertexs, size_t n)
:_vertexs(n)
,_chart(n,nullptr)
{
for (int i = 0; i < n; ++i)
{
_vertexs[i] = vertexs[i];
}
for (int i = 0; i < n; ++i)
{
_mapIndex[_vertexs[i]] = i;
}
}
bool AddEdge(const V& src, const V& dst, W w)
{
int srci = findIndex(src);
int dsti = findIndex(dst);
if (srci == dsti)
{
return false;
}
Edge* edge = new Edge(srci, dsti, w);
edge->_next = _chart[srci];
_chart[srci] = edge;
//无向图
if (direction == false)
{
Edge* edge = new Edge(dsti, srci, w);
edge->_next = _chart[dsti];
_chart[dsti] = edge;
}
return true;
}
int findIndex(const V& vertex)
{
auto it = _mapIndex.find(vertex);
if (it == _mapIndex.end())
{
cout << "没找到" << endl;
return -1;
}
//找到了
return it->second;
}
void print()
{
int n = _vertexs.size();
for (int i = 0; i < n; i++)
{
cout << _vertexs[i] << "->" << '[' << i << ']' << endl;
}
cout << endl;
for (int i = 0; i < n; i++)
{
Edge* cur = _chart[i];
while (cur != nullptr)
{
cout << _vertexs[cur->_srci] << "->" << _vertexs[cur->_dsti] << ":" << cur->_w << " ";
cur = cur->_next;
}
cout << "end" << endl;
}
}
private:
vector<V> _vertexs; // 所有点的集合
map<V, int> _mapIndex; // 找点的下标
vector<Edge*> _chart; // 领接图
};
void test()
{
Graph<char, int, INT_MAX, true> g("0123", 4);
g.AddEdge('0', '1', 1);
g.AddEdge('0', '3', 4);
g.AddEdge('1', '3', 2);
g.AddEdge('1', '2', 9);
g.AddEdge('2', '3', 8);
g.AddEdge('2', '1', 5);
g.AddEdge('2', '0', 3);
g.AddEdge('3', '2', 6);
g.print();
}