您的位置:首页 > 理论基础 > 数据结构算法

数据结构--图

2016-12-03 10:19 316 查看
图的基本概念:

1)图是由顶点的有穷非空集合顶点之间边的集合组成,通常表示为:G=(V ,E)

其中:G 表示一个图,V 是图G 中顶点的集合,E 是图G中顶点之间边的集合。

2)在图中,顶点个数不能为零,但可以没有边。

3)在图结构中,任意两个顶点之间都可能有关系。

4)在图结构中,顶点之间的关系为邻接

5)若代表一条边的顶点序偶是无序的(即该边无方向),则称此图为无向图。

若代表一条边的顶点序偶是有序的(即边有方向),则称此图为有向图。

6)任何两顶点间都有边相关联的图称为完全图(complete graph),完全图显然具有最大的边数。

7)邻接顶点:如果 (u, v) 是 E(G) 中的一条边,则称 u 与 v 互为邻接顶点。

8)子图:设有两个图G=(V, E)和G‘=(V’, E‘)。若 V’是 V的子集 且 E‘是E的子集, 则称图G’是图G的子图。

9)顶点的度:一个顶点v的度是与它相关联的边的条数。记作TD(v)。在有向图中, 顶点的度等于该顶点的入度与出度之和。

10)路径长度:

非带权图 —— 路径上边的个数

带权图 —— 路径上各边的

11) 连通图:如果图中任意两个顶点都是连通的 , 则称该图是连通图

12)连通分量非连通图极大连通子图称为连通分量 。

极大连通子图:含有极大顶点数;依附于这些顶点的所有边

连通分量是对无向图的一种划分!

12)生成树:n 个顶点的连通图 G的生成树是包含G中全部顶点的一个极小连通子图(含有n-1条边)

生成森林: 在非连通图中 , 由每个连通分量都可以得到一棵生成树 , 这些连通分量的生成树就组成了一个非连通图的生成森林 。

图的抽象数据类型:

class Graph {
public:
Graph ( );
void InsertVertex ( Type & vertex ); // 插入一个顶点
void InsertEdge ( int v1, int v2, int weight ); // 插入一条边
void RemoveVertex ( int v ); // 删除一个顶点
void RemoveEdge ( int v1, int v2 ); // 删除一条边
int IsEmpty ( ); // 判断图是否为空
Type GetWeight ( int v1, int v2 ); // 获取边的权重值
int GetFirstNeighbor ( int v ); // 获取第一个邻接顶点
int GetNextNeighbor ( int v1, int v2 );  // 获取下一个邻接顶点
}


图的存储表示:

邻接矩阵

1)在图的邻接矩阵表示中,有一个记录各个顶点信息顶点表,还有一个表示各个顶点之间关系邻接矩阵

2)无向图的邻接矩阵的主对角线为0且一定是对称的;

有向图的邻接矩阵可能是不对称的。

3)无向图顶点i的度为邻接矩阵的第i行(或第i列)非零元素的个数。

4)邻接矩阵中相应位置的元素arc[i][j] 为1说明顶点i和顶点j存在边。

5)无向图中将数组中第 i 行元素扫描一遍,若arc[i][j] 为1 ,则

顶点 j 为顶点 i 的邻接点。

6)当有向图为有向完全图时,其邻接矩阵也是对称的。

7)有向图顶点i的出度为邻接矩阵的第 i 行元素之和。

顶点i的入度为邻接矩阵的第 i 列元素之和。

邻接矩阵的实现:

定义两个数组分别存储顶点信息(数据元素)和边或弧的信息(数据元素之间的关系) 。

#include<iostream>
#include<string>
using namespace std;

#define INFINITY 2147483647 //最大值∞
#define MAX_VEX 30//最大顶点数目

typedef int VexType;
typedef int ArcValType;
typedef string ArcInfoType;
typedef int AdjType;
typedef enum{DG, AG, WDG, WAG} GraphKind; //{有向图,无向图,带权有向图,带权无向图}

//邻接矩阵的实现
typedef struct ArcType
{
VexType vex1,vex2;  //弧或边所依附的两个顶点
ArcValType ArcVal;  //弧或边的权值
ArcInfoType ArcInfo; //弧或边的其它信息
}ArcType;   //弧或边的结构定义

typedef struct
{
GraphKind kind; //图的种类标志
int vexnum,arcnum;  //图的当前顶点数和弧数
VexType vexs[MAX_VEX];  //顶点向量
ArcType adj[MAX_VEX][MAX_VEX];
}MGraph;    //图的结构定义

//图的顶点定位:确定一个顶点在vexs数组中的位置
int LocateVex(MGraph *G,VexType *vp)
{
int k;
for(k=0;k<G->vexnum;k++)
{
if(G->vexs[k]==*vp) return k;
}
return -1;  //图中无此顶点
}

//向图中增加一个顶点
void AddVex(MGraph *G,VexType *vp)
{
int k,j;
if(G->vexnum>=MAX_VEX)
{
cout<<"超出最大顶点数目\n";
return;
}
if(LocateVex(G,vp)!=-1)
{
cout<<"该顶点已经存在\n";
return;
}
k=G->vexnum;
G->vexs[G->vexnum++]=*vp;
if(G->kind==DG||G->kind==AG)
{
for(j=0;j<G->vexnum;j++)
{
G->adj[j][k].ArcVal=G->adj[k][j].ArcVal=0;
//是不带权的有向图或无向图
}
}
else
{
for(j=0;j<G->vexnum;j++)
{
G->adj[j][k].ArcVal=INFINITY;
G->adj[k][j].ArcVal=INFINITY;
//是带权的有向图或无向图
}
}
}

//向图中增加一条弧
void AddArc(MGraph *G,ArcType *arc)
{
int k,j;
k=LocateVex(G,&arc->vex1);
j=LocateVex(G,&arc->vex2);
if(k==-1||j==-1)
{
cout<<"该弧的顶点不存在"<<endl;
return;
}
if(G->kind==DG||G->kind==WDG)
{
G->adj[k][j].ArcVal=arc->ArcVal;
G->adj[k][j].ArcInfo=arc->ArcInfo;
//是有向图或带权的有向图
}
else
{
G->adj[k][j].ArcVal=G->adj[j][k].ArcVal=arc->ArcVal;
G->adj[k][j].ArcInfo=G->adj[j][k].ArcInfo=arc->ArcInfo;
//是无向图或带权的无向图,需对称赋
}
}


邻接表:当图中的边数较少时,相邻矩阵就会出现大量的零元素,存储这些零元素将耗费大量的存储空间。对于稀疏图,可以采用邻接表存储法。

邻接表(adjacency list)表示法是一种链式存储结构,由一个顺序存储的顶点表和n个链接存储的边表组成。

顶点表目有两个域:顶点数据域指向此顶点边表指针域

边表把依附于同一个顶点vi的边(即相邻矩阵中同一行的非0元素)组织成一个单链表。

边表中的每一个表目都代表一条边,由两个主要的域组成:

• 与顶点vi邻接的另一顶点的序号

• 指向边表中下一个边表目的指针



有向图有邻接表(出边表)和逆邻接表(入边表)之分。

邻接表的实现:

#include<iostream>
using namespace std;

//结点及其类型定义
#define MAX_VEX 30  //最大顶点数
typedef int InfoType;
typedef int VexType;
typedef enum {DG, AG, WDG, WAG}GraphKind;

typedef struct LinkNode{
int adjvex; //邻接点在头结点数组中的位置(下标)
InfoType info;  //与边或弧相关的信息, 如权值
struct LinkNode *nextarc;   //指向下一个表结点
}LinkNode;  //表结点类型定义

typedef struct VexNode{
VexType data;   //顶点信息
int indegree;   //顶点的度, 有向图是入度或出度或没有
LinkNode *firstarc; // 指向第一个表结点
}VexNode;   //顶点结点类型定义

typedef struct
{
GraphKind kind;
int vexnum;
VexNode AdjList[MAX_VEX];
}ALGraph;   //图的结构定义


可以发现,邻接表中每条边将会出现两个边结点。为了方便有关边的处理,我们使用邻接多重表。

邻接多重表:在邻接多重表中, 每一条边只有一个边结点。



需要时还可设置一个存放与该边相关的权值的域 cost

无向图:



有向图:



存储顶点信息的结点表以顺序表方式组织, 每一个顶点结点有两个数据成员:其中,data 存放与该顶点相关的信息,Firstout 是指示第一条依附该顶点的边的指针。

在邻接多重表中,所有依附同一个顶点的边都链接在同一个单链表中。

图的十字链表表示 :

#include<iostream>
using namespace std;

#define INFINITY 2147483647
#define MAX_VEX 30
typedef int InfoType;
typedef int VexType;

typedef struct ArcNode
{
int tailvex,headvex;    // 尾结点和头结点在图中的位置
InfoType info;
struct ArcNode *hlink,*tlink;
}ArcNode;   //弧结点类型定义

typedef struct VexNode
{
VexType data;
ArcNode *fristin,*firtstout;
}VexNode;   //顶点结点类型定义

typedef struct
{
int vexnum;
VexNode xlist[MAX_VEX];
}OLGraph;   //图的类型定义
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: