一、图的定义及基本术语
1.定义:由顶点的又穷非空集合和顶点之间边的集合的组成;表示为G=(V,E)其中V是点集合,E是边集合
图可以分为有向图以及无向图。若边含有数量值则这个值成为这条边上的权。
2.基本术语:
①邻接,依附:无向图中,对于任意两个顶点vi和顶点vj,若存在边(vi,vj),则称顶点vi和顶点vj互为邻接点,同时称边(vi,vj)依附于顶点vi和顶点vj。
②度,入度,出度:在无向图中,顶点v的度是指依附于该顶点的边数,通常记为TD (v);在有向图中,顶点v的入度是指以该顶点为弧头的弧的数目,记为ID (v);在有向图中,顶点v的出度是指以该顶点为弧尾的弧的数目,记为OD (v)。
③完全图:无向完全图:任意两顶点之间都有一条边,即n个顶点就有n*(n-1)/2条边。有向完全图:任意两顶点之间都存在方向相反的两条边,同样是n个顶点边数是无向完全图的2倍。
二、图的实现
1.图的存储:①邻接矩阵;②邻接表
①利用邻接矩阵:a[i][j]表示边 ;i,j表示两个点,0为不存在边,1为存在;
如何表示输入一条边? (输入边的邻接点 i与j 即cin>>i>>j;arc[i][j]=权值(1);)
声明:
class MGraph
{
public:
MGraph(){}
MGraph(int a[],int b[MaxSize][MaxSize],int n, int e );
private:
int vertex[MaxSize]; //顶点个数信息
int visited[MaxSize];
int arc[MaxSize][MaxSize];
int vertexNum, arcNum;
};
构建:
MGraph::MGraph(int a[],int b[MaxSize][MaxSize],int n, int e)
{
vertexNum=n; arcNum=e; int i,j;
for ( i=0; i<vertexNum; i++) {
vertex[i]=a[i];
visited[i]=0;
}
for ( i=0; i<vertexNum; i++) {//初始化邻接矩阵
for ( j=0; j<vertexNum; j++) {
arc[i][j]=0; }
}
for (int i=0; i<vertexNum; i++){//初始化邻接矩阵
for (int j=0; j<vertexNum; j++){
arc[i][j]=b[i][j]; }
}
}
深度遍历:
void MGraph::DFSTraverse(int v) //深度优先遍历
{
cout<<vertex[v];
visited [v]=1;
for (int j=0; j<vertexNum; j++)
{
if (arc[v][j]==1 && visited[j]==0)
DFSTraverse(j);
}
}
广度遍历:
void MGraph::BFSTraverse(int v) //广度优先遍历
{
queue<int> a;
cout<<vertex[v]; visited[v]=1; a.push(v);
while (!a.empty()) {
v=a.front(); a.pop();
for (int j=0; j<vertexNum; j++) {
if (arc[v][j]==1 && visited[j]==0 ) {
cout<<vertex[j];
visited[j]=1;
a.push(j); } } }
}
②邻接表
邻接表有顶点表结点和边表结点两种。前者存结点后者存与他邻接的点
顶点结点:
template <class T>
struct VertexNode
{
T vertex;
ArcNode *firstedge;
};
表结点:入度表/出度表
struct ArcNode
{
int adjvex;
ArcNode *next;
};
声明:
template <class T>
class ALGraph
{
public:
ALGraph(T a[ ], int n, int e);
void DFSTraverse(int v);
void BFSTraverse(int v);
private:
visited[MaxSize]; VertexNode adjlist[MaxSize];
int vertexNum, arcNum;
};
构建:(for循环 adjlist[i] 链表进行头插/尾插)
template <class T>
ALGraph::ALGraph(T a[], int n, int e)
{
vertexNum=n; arcNum=e;
for (i=0; i<vertexNum; i++)
{
adjlist[i].vertex=a[i]; visited[i]=0;
adjlist[i].firstedge=NULL;
}
for (k=0; k<arcNum; k++)
{
cin>>i>>j;
s=new ArcNode;
s->adjvex=j;
s->next=adjlist[i].firstedge;
adjlist[i].firstedge=s;
}
}
深度优先:
template <class T>
void ALGraph::DFSTraverse(int v)
{
cout<<adjlist[v].vertex;
visited[v]=1;
p=adjlist[v].firstedge;
while (p!=NULL) {
j=p->adjvex;
if (visited[j]==0) DFSTraverse(j);
p=p->next;
}
}
广度优先:
template <class T>
void ALGraph::BFSTraverse(int v)
{
front=rear=-1;
cout<<adjlist[v].vertex;
visited[v]=1;
Q[++rear]=v;
while (front!=rear) {
v=Q[++front];
p=adjlist[v].firstedge;
while (p!=NULL){
j= p->adjvex;
if (visited[j]==0) {
cout<<adjlist[j].vertex;
visited[j]=1;
Q[++rear]=j;
}
p=p->next;
}
邻接矩阵中的其他操作:
邻接矩阵中加边或加点:
加边: 输入已经i与j ;arc【i】【j】修改邻接矩阵即可;
加点:邻接矩阵遍历,增大MaxSize;对于arc【】【曾大后的Max Size】以及arc【增大后的Max Size】【】进行修改;
加点的代码:
template <class T>
void MGraph<T>::DeleteVex(int pos)
{
if ( pos<0|| pos>MaxSize) throw "位置";
int row, col;
int numv=vertexNum;
for(int i=pos;i<numv;i++)
vertex[i]=vertex[i+1];
vertexNum--;
for(row=0;row<numv;row++)
{ //删除一列
for(col=pos;col<numv;col++)
arc[row][col]=arc[row][col+1];
}
for(row=pos;row<numv;row++)
for(col=0;col<numv;col++)
arc[row][col]=arc[row+1][col];
}
}
删除一个点的思想与增加一个点一样的道理。