一、图的定义和基本术语
①顶点的有穷非空集合;②边的有穷集合(可以空)
1)无向图、有向图、无向网(带有权值的图)、有向网(带有权值的图);
2)①无向完全图:n(n-1)/2条边的无向图,也就是任两点都有直接的边;
②有向完全图:n(n-1)条边的有向图;
3)路径:路径是一个顶点序列,连续的边的顶点;
简单路径:序列中顶点不重复出现的路径;
4)连通:从一个顶点到另一个顶点有路径 ,则连通。区分邻接(有直接的边相连)
连通图:图中任两点都连通,该图即连通图(无向图);
强连通图:有向图的连通图;
连通分量:无向图中的极大 连通 子图(极大是指再加一个点就不连通了,而不是说顶点多);
强连通分量:有向图的连通分量;
5)生成树:极小连通子图,包含图的全部顶点;(下面有详细介绍);
二、图的存储结构
掌握①顺序存储结构:邻接矩阵表示法(数组表示法)
②链式存储结构:邻接表
了解十字链表
1.邻接矩阵(数组表示)
运用两个数组
①一维数组:存储顶点
②二维数组:arcs[i][j]=…(分图和网)
1)无向图(网):
①特点:
n个顶点为n阶矩阵;
无向图是对称的!
对角线元素为0或者∞(网)
顶点的度为第i行(列)中1的个数;
完全图的邻接矩阵中,除对角线元素外,其余元素均为1;
②无向图(网)的创建:
结构体如下:
#define MaxINT 0x7fffffff
#define MAXSIZE 1000
struct Graph{
int vexnum;
int arcnum;
char Vexs[1000];
int arcs[1000][1000];
}G;
构建(以无向网为例):
输入顶点数n、边数;
依次输入顶点信息
下面m行输入边的依附点和权值
int LocateVex(char ch)
{
for(int i=0;i<G.vexnum;i++)
{
if(ch==G.Vexs[i])
return i;
}
return -1;
}
void CreatGraph()
{
cin>>G.vexnum>>G.arcnum;
getchar();
for(int i=0;i<G.vexnum;i++)
{
for(int j=0;j<G.vexnum;j++)
{
G.arcs[i][j]=MAX;
}
}
char a,b;
int x;
for(int i=0;i<G.vexnum;i++)
{
cin>>G.Vexs[i];
}
for(int j=0;j<G.arcnum;j++)
{
getchar();
cin>>a>>b;
int t=LocateVex(a);
int h=LocateVex(b);
cin>>x;
G.arcs[t][h]=x;
G.arcs[h][t]=x;
}
}
2)有向图(网)
①特点:
矩阵是不对称的
行和为出度;列和为入度。顶点的度为行和加列和
赋值时仅需为G.arcs[i][j]赋值,无需为G.arcs[j][i]赋值;
②创建与无向图类似
3)优缺点:
①优点:a.求度方便;b.判断两点之间有无边比较方便;c.求邻接点方便;
②缺点:a.不便于增删;b.若为稀疏图,比较浪费空间
2.邻接表
对于每个顶点建立一个单链表,链接依附于它的边,请参照头结点和边结点的结构图;
每个单链表有一个头结点,存储顶点信息;
将表头节点以顺序结构存储(常用数组)
1) 无向图的创建
①结构体
#define MaxVertexNum 10 /* 最大顶点数设为10 */
typedef int Vertex; /* 用顶点下标表示顶点,为整型 */
/* 邻接点的定义 */
typedef struct AdjVNode *PtrToAdjVNode;
struct AdjVNode{
Vertex AdjV; /* 邻接点下标 */
PtrToAdjVNode Next; /* 指向下一个邻接点的指针 */
};
/* 顶点表头结点的定义 */
typedef struct Vnode{
int data;
PtrToAdjVNode FirstEdge; /* 边表头指针 */
} AdjList[MaxVertexNum]; /* AdjList是邻接表类型 */
/* 图结点的定义 */
typedef struct GNode *PtrToGNode;
struct GNode{
int Nv; /* 顶点数 */
int Ne; /* 边数 */
AdjList G; /* 邻接表 */
};
typedef PtrToGNode LGraph; /* 以邻接表方式存储的图类型 */
②创建(例)
输入:
7 9//顶点n,边数m
0 4
0 2
0 3
1 3
1 5
2 3
2 5
4 5
5 6
LGraph CreateGraph()
{
LGraph M;
M=(LGraph)malloc(sizeof(struct GNode));
int n,m;
scanf("%d%d",&n,&m);//输入顶点数、边数
M->Nv=n;
M->Ne=m;
for(int i=0;i<n;i++)//图的初始化
{
M->G[i].data=i;
M->G[i].FirstEdge=NULL;//初始化将头结点的指针域置空
}
for(int i=0;i<m;i++