图的两种存储方式
一、邻接矩阵:
邻接矩阵的结构定义
typedef struct
{
int no; //顶点编号
char info; //存储顶点的其他信息
}VertexType;
typedef struct //图的定义
{
int edges[maxsize][maxsize]; //定义二维数组存储边的关系
int n,e; //存储顶点数和边数
VertexType vex[maxsize]; //存储节点信息
}MGraph;
二、邻接表的结构定义
typedef struct AcNode
{
int adjvex;
struct AcNode *nextarc;
}AcNode; //定义链表的节点
typedef struct VNode
{
int data;
struct VNode *firstAcNode;
}VNode; //定义顶点
typedef struct
{
VNode adjlist[maxsize];
int n,e;
}AGraph;
///
图的深度优先遍历
(以邻接表为存储结构)
int visit[maxsize]; //存储节点访问信息,初始化为0。因图中可能存在环路,当前节点将来可能再次经过,因此要对每个顶点进行标记,以免重复访问
void DFS(AGraph *G, int v)
{
AcNode *p;
visit[v] = 1;
Visit(v); //Visit函数代表一类访问顶点v操作
p = G->adjlist[v].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0) //若为被访问,则递归访问
DFS(G,p->adjvex);
p = p->nextarc;
}
}
图的广度优先遍历(需要借助队列实现)
(以邻接表为存储结构)
void BFS(AGraph G, int v, int visit[maxsize])
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
Visit(v); //Visit函数代表一类访问顶点v操作
visit[v] = 1;
rear = (rear+1)%maxsize; //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize; //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
Visit(p->adjvex);
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize; //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;
}
}
}
例题1:
设计算法,求不带权无向连通图图G中距离顶点v最远的一个顶点(最远是指到达v路径长度最长)
分析:图的广度优先搜索遍历方式体现由图中某个顶点开始,以由近向远层层扩展的方式遍历图中节点的过程。及最后遍历节点即为最远节点
int BFS(AGraph *G, int v)
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
int visit[maxsize] = 0; //初始化为0
visit[v] = 1;
rear = (rear+1)%maxsize; //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize; //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize; //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;
}
}
return j;
}
例题2:
设计算法,判断无向图G是否是一棵树。若是返回1,否则返回0
分析:一个无向图是一棵树的条件是有n-1 条边的连通图,n为图中顶点个数。边和顶点的数目是否满足条件可由图的信息直接判断,连通与否可以用遍历能否访问到所有顶点来判断。
void DFS(AGraph *G, int v, int &vn, int &en)
{
AcNode *p;
visit[v] = 1;
++vn;
p = G->adjlist[v].firstAcNode;
while(p != NULL)
{
++en;
if(visit[p->adjvex] == 0)
DFS(G,p->adjvex,vn,en);
p = p->nextarc;
}
}
int GisTree(AGraph *G)
{
int vn = 0, en = 0;
int i;
for(i = 1; i <= G->n; ++i)
visit[i] = 0;
DFS(G, 1, vn, en);
if(vn == G->n && (G->n-1) == en/2)
//如果遍历过程中访问过的顶点和图中顶点数相等,且边数等于顶点数减1,即证明是树
return 1;
else
return 0;
}
一、邻接矩阵:
邻接矩阵的结构定义
typedef struct
{
int no; //顶点编号
char info; //存储顶点的其他信息
}VertexType;
typedef struct //图的定义
{
int edges[maxsize][maxsize]; //定义二维数组存储边的关系
int n,e; //存储顶点数和边数
VertexType vex[maxsize]; //存储节点信息
}MGraph;
二、邻接表的结构定义
typedef struct AcNode
{
int adjvex;
struct AcNode *nextarc;
}AcNode; //定义链表的节点
typedef struct VNode
{
int data;
struct VNode *firstAcNode;
}VNode; //定义顶点
typedef struct
{
VNode adjlist[maxsize];
int n,e;
}AGraph;
///
图的深度优先遍历
(以邻接表为存储结构)
int visit[maxsize]; //存储节点访问信息,初始化为0。因图中可能存在环路,当前节点将来可能再次经过,因此要对每个顶点进行标记,以免重复访问
void DFS(AGraph *G, int v)
{
AcNode *p;
visit[v] = 1;
Visit(v); //Visit函数代表一类访问顶点v操作
p = G->adjlist[v].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0) //若为被访问,则递归访问
DFS(G,p->adjvex);
p = p->nextarc;
}
}
图的广度优先遍历(需要借助队列实现)
(以邻接表为存储结构)
void BFS(AGraph G, int v, int visit[maxsize])
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
Visit(v); //Visit函数代表一类访问顶点v操作
visit[v] = 1;
rear = (rear+1)%maxsize; //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize; //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
Visit(p->adjvex);
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize; //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;
}
}
}
例题1:
设计算法,求不带权无向连通图图G中距离顶点v最远的一个顶点(最远是指到达v路径长度最长)
分析:图的广度优先搜索遍历方式体现由图中某个顶点开始,以由近向远层层扩展的方式遍历图中节点的过程。及最后遍历节点即为最远节点
int BFS(AGraph *G, int v)
{
AcNode *p;
int que[maxsize],front = 0,rear = 0;
int j;
int visit[maxsize] = 0; //初始化为0
visit[v] = 1;
rear = (rear+1)%maxsize; //当前节点进队
que[rear] = v;
while(front != rear)
{
front = (front+1)%maxsize; //顶点出队
j = que[front];
p = G->adjlist[j].firstAcNode;
while(p != NULL)
{
if(visit[p->adjvex] == 0)
{
visit[p->adjvex] = 1;
rear = (rear+1)%maxsize; //该顶点进队
que[rear] = p->adjvex;
}
p = p->nextarc;
}
}
return j;
}
例题2:
设计算法,判断无向图G是否是一棵树。若是返回1,否则返回0
分析:一个无向图是一棵树的条件是有n-1 条边的连通图,n为图中顶点个数。边和顶点的数目是否满足条件可由图的信息直接判断,连通与否可以用遍历能否访问到所有顶点来判断。
void DFS(AGraph *G, int v, int &vn, int &en)
{
AcNode *p;
visit[v] = 1;
++vn;
p = G->adjlist[v].firstAcNode;
while(p != NULL)
{
++en;
if(visit[p->adjvex] == 0)
DFS(G,p->adjvex,vn,en);
p = p->nextarc;
}
}
int GisTree(AGraph *G)
{
int vn = 0, en = 0;
int i;
for(i = 1; i <= G->n; ++i)
visit[i] = 0;
DFS(G, 1, vn, en);
if(vn == G->n && (G->n-1) == en/2)
//如果遍历过程中访问过的顶点和图中顶点数相等,且边数等于顶点数减1,即证明是树
return 1;
else
return 0;
}