1.图的概念
图是有顶点集合以及顶点的关系集合组成的一种数据结构。
a)完全图:由n个顶点组成的无向图,若有n*(n-1)/2条边,则称为无向图完全图。
在由n个顶点组成的有向图中,若有n*(n-1)条边,则称之为有向完全图。
b)权:在某些图中,边具有与之相关的数值,称为权重。权重可以表示从一个顶点到另一个顶点的距离、花费的代价等等。这种带权图也叫作网络。
c)度:与顶点v关联的边数称为度。在有向图中顶点的度数等于其入度加出度之和。入度是指以结点为终点的边 ,出度是指以结点为起点的边。
d)连通图:
在图论中,连通图基于连通的概念。在一个无向图 G 中,若从顶点vi到顶点vj有路径相连(当然从vj到vi也一定有路径),则称vi和vj是连通的。如果 G 是有向图,那么连接vi和vj的路径中所有的边都必须同向。如果图中任意两点都是连通的,那么图被称作连通图。如果此图是有向图,则称为强连通图(注意:需要双向都有路径)。
e)连通分量:连通分量:无向图 G的一个极大连通子图称为 G的一个连通分量(或连通分支)。连通图只有一个连通分量,即其自身;非连通的无向图有多个连通分量。
2.邻接矩阵:
所谓邻接矩阵(Adjacency Matrix)的存储结构,就是用一维数组存储图中顶点的信息,用矩阵表示图中各顶点之间的邻接关系。假设图G=(V,E)有n 个确定的顶点,即V={v0,v1,…,vn-1},则表示G 中各顶点相邻关系为一个n×n 的矩阵,矩阵的元素为:
用邻接矩阵表示法表示图如图8.7 所示:
3.代码 实现:
Graphmtx.h
#ifndef GRAPHMTX_H
#define GRAPHMTX_H
#include<Graph.h>
#include<iostream>
#include<stdlib.h>
using namespace std;
template <class T,class E>
class Graphmtx
{
public:
E maxWeight;
/** Default constructor */
Graphmtx(int sz=DefaultVertices)
{
maxVertices=sz;
numVertices=0;
numEdges=0;
VerticesList =new T[maxVertices];
Edge =(E **)new E *[maxVertices];
//初始化邻接矩阵
for(int i=0; i<maxVertices; i++)
Edge[i]=new E[maxVertices];
for(int i=0; i<maxVertices; i++)
for(int j=0; j<maxVertices; j++)
Edge[i][j]=i==j?0:maxWeight;
}
/** Default destructor */
~Graphmtx()
{
delete []VerticesList;
delete Edge;
}
//当前定点数
int NumberOfvertices()
{
return numVertices;
}
//返回当前边数
int NumberOfEdges()
{
return numEdges;
}
//获取顶点的值
T getValue(int i)
{
return i>=0&&i<numVertices?VerticesList[i]:NULL;
}
//获取边上的权值
E getWeight(int v1,int v2)
{
return -1!=v1&&-1!=v2?Edge[v1][v2]:0;
}
//获取顶点v的第一个邻接顶点
int getFirstNeighbor(int v)
{
if(-1!=v)
{
for(int col=0; col<numVertices; col++)
if(Edge[v][col]>0&&Edge[v][col]<maxWeight)
return col;
}
return -1;
}
//获取v的邻接顶点w的下一邻接顶点
int getNextNeighbor(int v,int w)
{
if(-1!=v&&-1!=w)
for(int col=w+1; col<maxVertices; col++)
if(Edge[v][col]>0&&Edge[v][col]<maxWeight)
return col;
return -1;
}
//插入顶点
bool insertVertex(const T &vertex)
{
if(numVertices==maxVertices)
return false;
VerticesList[numVertices++]=vertex;
return true;
}
//插入边
bool insertEdge(int v1,int v2,const E cost)
{
if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]==maxWeight)
{
Edge[v1][v2]=Edge[v2][v1]=cost;
numEdges++;
return true;
}
return false;
}
//删除顶点v以及所有与之关联的边
bool removeVertex(int v)
{
//v不在图中不删除
if(v<0||v>numVertices)
return false;
//只剩下一个顶点,不删除
if(1==numVertices)
{
return false;
}
VerticesList[v]=VerticesList[numVertices-1];
//减去与v相关联的边
for(int i=0; i<numVertices; i++)
if(Edge[v][i]>0&&Edge[v][i]<maxWeight)
numEdges--;
//用最后一列填补第
for(int i=0; i<numVertices; i++)
Edge[i][v]=Edge[i][numVertices-1];
numVertices--;
//用最后一行填补第v行
for(int i=0; i<numVertices; i++)
Edge[v][i]=Edge[numVertices-1][i];
return true;
}
//删除边(v1,v2)
bool removeEdge(int v1,int v2)
{
if(v1>-1&&v1<numVertices&&v2>-1&&v2<numVertices&&Edge[v1][v2]>0&&Edge[v1][v2]<maxWeight)
{
Edge[v1][v2]=Edge[v2][v1]=maxWeight;
numEdges--;
return true;
}
return false;
}
template <class V,class W>
friend istream& operator >>(istream & in,Graphmtx<V,W> &G);
template <class V,class W>
friend ostream& operator<<(ostream &out,Graphmtx<V,W> &G);
private:
//最大的顶点树
int maxVertices;
//当前边数
int numEdges;
//当前顶点树
int numVertices;
//顶点表
T *VerticesList;
//邻接矩阵
E **Edge;
//给出顶点在图中的位置
int getVertexPos(T vertex)
{
for(int i=0; i<numVertices; i++)
{
if(VerticesList[i]==vertex)
return i;
}
return -1;
}
};
#endif // GRAPHMTX_H
main.cpp
#include <iostream>
#include<Graphmtx.h>
using namespace std;
int main()
{
Graphmtx<int,int> G(5);
cin>>G;
cout<<G;
return 0;
}
template <class V,class W>
istream& operator >>(istream & in,Graphmtx<V,W> &G)
{
//n是顶点数,m是边数
int n,m;
V e1,e2;
W weight;
cout<<"请输入顶点数、边数:"<<endl;
in>>n>>m;
cout<<"请输入顶点:"<<endl;
for(int i=0; i<n; i++)
{
in>>e1;
G.insertVertex(e1);
}
int i=0,j,k;
cout<<"请输入边的两个顶点以及权值:"<<endl;
while(i<m)
{
in>>e1>>e2>>weight;
j=G.getVertexPos(e1);
k=G.getVertexPos(e2);
if(-1==j&&-1==k)
{
cout<<"边的两端信息有误,请重新输入。"<<endl;
}
else
{
G.insertEdge(j,k,weight);
i++;
}
}
return in;
}
template <class V,class W>
ostream& operator<<(ostream &out,Graphmtx<V,W> &G)
{
//输出所有顶点和边的信息
int n,m;
V e1,e2;
W w;
n=G.NumberOfvertices();
m=G.NumberOfEdges();
out<<"一共有顶点数:"<<n<<"个 边:"<<m<<"条"<<endl;
for(int i=0; i<n; i++)
for(int j=i+1; j<n; j++)
{
w=G.getWeight(i,j);
if(w>0&&w<G.maxWeight)
{
e1=G.getValue(i);
e2=G.getValue(j);
out<<"("<<e1<<","<<e2<<","<<w<<")"<<endl;
}
}
return out;
}
工程源码请点击我的GitHub