一、图的相关概念
1、图(Graph):是由一种由顶点(Vertex)非空有限集合和顶点之间边(Edge)的集合组成的数据结构,表示为G(V,E)。
其中,G为图,V为顶点集合,E为边的集合。顶点集合有穷非空,边集合可以为空。
2、基本类型:
(1)、按边的方向有无可分为有向图和无向图,有向图的边又称为弧。
(2)、按边的多少分为稠密图和稀疏图
(3)、边(弧)上带权的图称为带权图,又称为网。
3、子图:顶点集和边集都是原图的子集的图称为子图。
4、邻接点:中间存在一条边的两个顶点,称这条边与两个顶点相关联。
5、度:在无向图中,度为与该顶点相关联的边的数目;在有向图中,度为入度和出度之和。
若一个图有n个顶点和e条边,e = 1/2∑di(1 ≤ i ≤ n)
6、路径长度:两点路径之间的边数,若一条路径的起点和终点相同,则此路径称为回路和环。
不带回路的图称为无环图。
7、连通性:
(1)、无向图:如果两个顶点之间存在路径,则两个顶点连通。如果任意两个顶点都连通,则无向图G为连通图,否则为非连通图,无向图的最大连通子图称为连通分量。
任何连通图的连通分量只有自己本身,而非连通图有多个连通分量。
(2)、有向图:如果从v到u和u到v之间都存在路径,则两个顶点u、v连通。如果有向图中的任意两个顶点都连通,则称有向图G为强连通图。有向图的最大强连通子图为该有向图的强连通分量。
强连通图只有一个强连通分量,即自己本身,非强连通图有多个强连通分量。
8、生成树:对于n个顶点的连通图G,如果存在连通子图G1包含G的所有顶点和一部分边,且不形成回路,称G1为G的生成树。
G1有n个顶点和n-1条边。生成树也称为极小连通子图,生成树不唯一。
9、有向树:有向图中一个顶点入度为0,其他顶点入度为1的连通子图。
二、图的性质
1、在一个具有n个顶点的无向图中,设边数为e,则0 ≤ e ≤
2、在一个具有n个顶点的有向图中,设边数为e,则0 ≤ e ≤ n(n-1)
三、图类的定义(邻接矩阵表示)
#include <iostream>
#include <stack>
#include <queue>
using namespace std;
enum GraphKind {DG, UDG, DN, UDN};
/*有向图,无向图,有向网,无向网*/
class Edge
{
public:
int Start;
int End;
int Weight;
Edge ( int Start, int End );
Edge ( int Start, int End, int Weight );
};
Edge::Edge ( int Start, int End )
{
this->Start = Start;
this->End = End;
}
Edge::Edge ( int Start, int End, int Weight )
{
this->Start = Start;
this->End = End;
this->Weight = Weight;
}
class AdjGraph
{
public:
int *vertex;//指向顶点数组的指针
int **matrix;//指向邻接矩阵的指针
int vertexNum;//顶点数
int edgeNum;//边数
enum GraphKind kind;//图的类型
int *Mark;
AdjGraph ( int Vertex );
~AdjGraph();
void setEdge ( AdjGraph & G, int start, int end );//设置图的边
void setEdge ( AdjGraph & G, int start, int end, int weight ); //设置网的边
void setEdgeNum ( int EdgeNum );//设置边的数量
int getEdgeNum();//获取边的数量
void CreateGraph ( AdjGraph & G, enum GraphKind kind );//创建图/网
void Clear ( AdjGraph & G );//清空图/网
void PrintGraph ( AdjGraph G );//打印图/网
};
AdjGraph::AdjGraph ( int Vertex )
{
vertexNum = Vertex;
edgeNum = 0;
}
AdjGraph::~AdjGraph()
{
vertexNum = 0;
edgeNum = 0;
delete vertex;
vertex = NULL;
for ( int i = 0; i < vertexNum ; i++ )
{
delete matrix[i];
matrix[i] = NULL;
}
delete matrix;
}
void AdjGraph::setEdge ( AdjGraph & G, int start, int end )
{
Edge e ( start, end );
if ( G.kind == UDG ) //无向图
{
G.matrix[start - 1][end - 1] = 1;
G.matrix[end - 1][start - 1] = 1;
}
else if ( G.kind == DG ) //有向图
{
G.matrix[start - 1][end - 1] = 1;
}
}
void AdjGraph::setEdge ( AdjGraph& G, int start, int end, int weight )
{
Edge e ( start, end, weight );
if ( G.kind == UDN )
{
G.matrix[start - 1][end - 1] = weight;
G.matrix[end - 1][start - 1] = weight;
}
else if ( G.kind == DN )
{
G.matrix[start - 1][end - 1] = weight;
}
}
void AdjGraph::setEdgeNum ( int EdgeNum )
{
edgeNum = EdgeNum;
}
int AdjGraph::getEdgeNum()
{
return edgeNum;
}
void AdjGraph::CreateGraph ( AdjGraph& G, enum GraphKind kind )
{
G.vertex = new int[G.vertexNum];
for ( int i = 0; i < G.vertexNum; i++ )
{
G.vertex[i] = i + 1;
}
G.matrix = new int*[G.vertexNum];//创建行的一维指针
for ( int i = 0; i < G.vertexNum; i++ )
{
G.matrix[i] = new int[G.vertexNum];//为每行开辟空间
}
G.kind = kind;
for ( int i = 0; i < G.vertexNum; i++ )
{
for ( int j = 0; j < G.vertexNum; j++ )
{
if ( G.kind == DG || G.kind == UDG )
{
G.matrix[i][j] = 0;
}
else
{
G.matrix[i][j] = INT_MAX;
}
}
}
}
void AdjGraph::Clear ( AdjGraph & G )
{
vertexNum = 0;
edgeNum = 0;
delete G.vertex;
G.vertex = NULL;
for ( int i = 0; i < G.vertexNum ; i++ )
{
delete G.matrix[i];
G.matrix[i] = NULL;
}
delete G.matrix;
}
void AdjGraph::PrintGraph ( AdjGraph G )
{
int i, j;
if ( G.vertexNum != 0 )
{
for ( i = 0; i < G.vertexNum; i++ )
{
for ( j = 0; j < G.vertexNum; j++ )
{
if ( G.matrix[i][j] == INT_MAX )
{
cout << "∞" << " ";
}
else
{
cout << G.matrix[i][j] << " ";
}
}
cout << endl;
}
}
else
{
cout << "图为空" << endl;
}
}
int main()
{
AdjGraph G1 ( 5 );
G1.setEdgeNum ( 6 );
G1.CreateGraph ( G1, UDG );//无向图
G1.setEdge ( G1, 1, 2 );
G1.setEdge ( G1, 1, 4 );
G1.setEdge ( G1, 2, 3 );
G1.setEdge ( G1, 3, 4 );
G1.setEdge ( G1, 3, 5 );
G1.setEdge ( G1, 2, 5 );
G1.PrintGraph ( G1 );
cout << endl;
AdjGraph G2 ( 4 );
G2.setEdgeNum ( 4 );
G2.CreateGraph ( G2, DG ); //有向图
G2.setEdge ( G2, 1, 2 );
G2.setEdge ( G2, 1, 3 );
G2.setEdge ( G2, 4, 1 );
G2.setEdge ( G2, 3, 4 );
G2.PrintGraph ( G2 );
cout << endl;
AdjGraph G3 ( 6 );
G3.setEdgeNum ( 9 );
G3.CreateGraph ( G3, DN ); //有向网
G3.setEdge ( G3, 1, 2, 50 );
G3.setEdge ( G3, 2, 3, 40 );
G3.setEdge ( G3, 4, 3, 50 );
G3.setEdge ( G3, 5, 4, 50 );
G3.setEdge ( G3, 6, 5, 10 );
G3.setEdge ( G3, 6, 1, 30 );
G3.setEdge ( G3, 1, 4, 70 );
G3.setEdge ( G3, 4, 6, 60 );
G3.setEdge ( G3, 3, 6, 90 );
G3.PrintGraph ( G3 );
return 0;
}