【C++】图的定义及性质

一、图的相关概念

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;
}

猜你喜欢

转载自blog.csdn.net/L____________/article/details/84636981