实验目的及要求:
1. 复习图的结构定义及其相关术语,理解图结构与树结构以及线性结构的明显区别;
2. 理解并掌握图的顺序存储结构(邻接矩阵表示法)、图的链式存储结构(邻接表表示法)。
3. 理解图的遍历问题所面临的困难,深度优先搜索和广度优先搜索的遍历策略,掌握基于递归的深度优先搜索和非递归的深度优先搜索算法,以及广度优先搜索算法。
4. 理解图的连通性以及最小代价生成树概念和最小生成树的Prime和Kruskal算法,理解有向无环图用于拓扑排序和求关键路径问题及其算法。
实验内容:(任务二、三都是选做)
任务一:编写算法完成图的存储结构建立与图的遍历:
- 先依次输入无向图的顶点信息,再依次输入无向图的边信息,建立图的邻接矩阵存储结构并将其顶点向量和邻接矩阵输出:
- 先依次输入有向图的顶点信息,再依次输入有向图的弧信息,建立图的邻接表存储结构并将其打印输出;
- 在1中建立的无向图的邻接矩阵存储结构基础上使用递归法对图进行深度优先搜索遍历并输出顶点序列;
- 在2中建立的有向图的邻接表存储结构基础上使用非递归算法对图进行深度优先搜索遍历并输出顶点序列;
- 分别在1中建立的无向图邻接矩阵存储结构基础上和在2中建立的有向图的邻接表存储结构基础上对图进行广度优先搜索遍历并输出顶点序列。
任务二:【选做】编写算法求无向连通图的最小代价生成树:
先依次输入无向图的顶点,再依次输入无向图的带权边信息,建立图的邻接矩阵或邻接表存储结构,判断该图是否是连通图,如果是连通图则利用Prim算法得到最小代价生成树,输出最小生成树的边信息以及最小代价。
任务三:【选做】编写算法求AOE网的关键路径:
先依次输入有向图的顶点信息,再一次输入有向图的带权弧信息,建立图的邻接矩阵或邻接表存储结构,判断该图是否为AOE网(图中存在一个唯一入度为0的顶点称为源点,存在唯一的出度为0的顶点称为汇点),若是AOE网则求一条从源点到汇点的关键路径并输出该路径及其路径长度。
程序代码:
根据任务一可知,任务要求为(1)无向图的邻接矩阵的dfs和bfs
- 有向图的邻接表的dfs和bfs
所以我将1,3,5合并为源文件1
2,4,5合并为源文件2
源文件1:(1,3,5)
算法为:
#include<stdio.h>
#include<stdlib.h>
#define MAXSIZE 100
int flag[MAXSIZE];
int Vist[MAXSIZE];
typedef struct Queue{
int data[MAXSIZE];
int head;
int wei;
}Queue;
typedef struct Matrix{
int V_Data;
int E_Data;
int Node[MAXSIZE];
int Weight[MAXSIZE][MAXSIZE];
}MaTrix,*MATRIX;
typedef struct Edge{
int v1;
int v2;
int weight;
}*EDGE;
void Init_Matrix(MATRIX S,int Vertex)
{
- >E_Data = 0;
- S->V_Data = Vertex;
int i,j;
for(i=0;i<Vertex;i++)
{
for(j=0;j<Vertex;j++)
{
S->Weight[i][j] = 0;
}
}
}
void InSerData(MATRIX S,EDGE E)
{
S->Weight[E->v1][E->v2] = E->weight;
S->Weight[E->v2][E->v1] = E->weight;
}
void DFS_Begin(MATRIX P,int k,int V)
{
int i;
flag[k] = 1;
printf("%d ",P->Node[k]);
for(i=0;i<V;i++)
{
if(!flag[i] && P->Weight[k][i] != 0)
{
DFS_Begin(P,i,V); }
}
}
void Init_DFSMatrix(MATRIX P,int V)
{
int i;
for(i=0;i<V;i++)
{
flag[i] = 0;
}
for(i=0;i<V;i++)
{
if(!flag[i])
DFS_Begin(P,i,V);
}
putchar('\n');
}
void InitQueue(Queue *q)
{
q->head= 0;
q->wei = 0;
}
int EmptyQueue(Queue *q)
{
if(q->head == q->wei)
return 1;
else{
return 0;
}
}
void PushQueue(Queue *q,int t)
{
if((q->wei+1)%MAXSIZE == q->head)
return;
else{
q->data[q->wei] = t;
q->wei = (q->wei +1)%MAXSIZE; }
}
void PopQueue(Queue *q,int *x)
{
if(q->wei == q->head)
return;
else{
*x = q->data[q->head];
q->head = (q->head + 1)%MAXSIZE; // 队头后移
}
}
void Init_Bfs(MATRIX S,int V)
{
int i,j;
int k;
Queue Q;
for(i=0;i<V;i++)
{
Vist[i] = 0;
}
InitQueue(&Q);
for (i = 0; i < V; i++)
{
if (!Vist[i]) {
Vist[i] = 1;
printf("%d ", S->Node[i]);
PushQueue(&Q, i);
while (!EmptyQueue(&Q)) {
PopQueue(&Q,&i);
for (j = 0; j < V; j++)
{
if (!Vist[j] && S->Weight[i][j] != 0)
{
Vist[j] = 1;
printf("%d ", S->Node[j]);
PushQueue(&Q, j); }
}
}
}
}
}
int Init_Vertex()
{
int Vertex;
printf("请输入顶点个数: ");
scanf("%d",&Vertex);
return Vertex;
}
int Init_Edge()
{
int edge;
printf("请输入边的数量: ");
scanf("%d",&edge);
return edge;
}
void InSerEdge_Data(MATRIX S,int edge,int V)
{
int i,j;
if(edge>0)
{
printf("请输入顶点和权重(空格分隔!)\n");
for(i=0;i<edge;i++)
{
EDGE E;
E = (EDGE)malloc(sizeof(struct Edge));
scanf("%d %d %d",&(E->v1),&(E->v2),&(E->weight));
if(E->v1 ==E->v2)
{
printf("无向图邻接矩阵对角线为0,输入错误,结束运行\n");
exit(-1);
}
InSerData(S,E);
}
printf("请输入要定义的顶点,填入顶点表中: \n");
for(j=0;j<V;j++)
{
scanf("%d",&(S->Node[j]));
}
}else{
printf("输入的边数错误");
}
}
void Show_Matrix(MATRIX p,int Vertex)
{
int i,j;
for(i=0;i<Vertex;i++)
{
for(j=0;j<Vertex;j++)
{
printf("%4d",p->Weight[i][j]);
}
putchar('\n'); }
}
int main()
{
int val;
int Vertex;
int edge;
MATRIX p;
Vertex = Init_Vertex();
edge = Init_Edge();
p = (MATRIX)malloc(sizeof(MaTrix));
p->V_Data = Vertex;
p->E_Data = edge;
Init_Matrix(p,Vertex);
InSerEdge_Data(p,edge,Vertex);
printf("无向图邻接矩阵如下:");
printf("\n----------------------------------\n\n");
Show_Matrix(p,Vertex);
printf("\n----------------------------------\n");
printf("深度遍历—邻接矩阵结果为:\n");
Init_DFSMatrix(p,Vertex);
printf("广度优先遍历—邻接矩阵结果为: \n");
Init_Bfs(p,Vertex);
return 0;
}
代码为:
#include <stdio.h>
#include <stdlib.h>
#define MaxSize 10
int visited1[MaxSize]={0};
int visited2[MaxSize]={0};
typedef char DataType;
typedef struct
{
DataType vertex[MaxSize];
int edge[MaxSize][MaxSize];
int vertexNum,edgeNum;
}MGraph;
void CreatGraph(MGraph *G,DataType a[],int n,int e);
void DFTravere(MGraph *G,int v);
void BFTraverse(MGraph *G,int v);
void CreatGraph(MGraph *G,DataType a[],int n,int e)
{
int i,j,k;
G->vertexNum=n;
G->edgeNum=e;
for(i=0;i<G->vertexNum;i++){
G->vertex[i]=a[i];
}
for(i=0;i<G->vertexNum;i++){
for(j=0;j<G->vertexNum;j++)
G->edge[i][j]=0;
}
for(k=0;k<G->edgeNum;k++){
scanf("%d %d",&i,&j);
G->edge[i][j]=1;
G->edge[j][i]=1;
}
}
void DFTraverse(MGraph *G,int v)
{
int j;
printf("%c",G->vertex[v]);
visited1[v]=1;
for(j=0;j<G->vertexNum;j++)
if(G->edge[v][j]==1&&visited1[j]==0)
DFTraverse(G,j);
}
void BFTraverse(MGraph *G,int v)
{
int i,j,Q[MaxSize];
int front,rear;
front=-1,rear=-1;
printf("%c",G->vertex[v]);
visited2[v]=1;
Q[++rear]=v;
while(front!=rear){
v=Q[++front];
for(j=0;j<G->vertexNum;j++){
if(G->edge[v][j]==1&&visited2[j]==0)
{
printf("%c",G->vertex[j]);
visited2[j]=1;
Q[++rear]=j;
}
}
}
}
int main()
{
char ch[]={'A','B','C','D','E'};
MGraph MG;
CreatGraph(&MG,ch,5,6);
printf("深度优先遍历序列是:");
DFTraverse(&MG,0);
printf("\n广度优先遍历序列是:");
BFTraverse(&MG,0);
return 0;
}