一、实验目的
1、 理解图的存储结构与基本操作;
2、 掌握图的创建过程
二、实验内容
1.根据下图,采用邻接矩阵的存储结构保存此图,并打印出邻接矩阵。
图的创建代码参考教材.
提示:首先根据给出的图结构得出该图的顶点集和边集,调用相应的函数生成图的邻接矩阵,并打印出邻接矩阵。
2.根据上一题的邻接矩阵,编程实现该图的深度与广度优先遍历算法,从顶点1开始遍历,分别输出深度与广度优先遍历序列。
3.选做题:单源最短路径问题
问题描述:求从有向图的某一结点出发到其余各结点的最短路径。
基本要求:
(1)有向图采用邻接矩阵表示。
(2)单源最短路径问题采用Dijkstra算法。
(3)输出有向图中从源结点A到其余各结点的最短路径和最短路径值。
三、【实验源代码】
头文件
typedef struct
{
int list[100];
int size;
}SequenceList;
int ListInitiate(SequenceList *L)
{
L->size = 0;
}
int ListInsert(SequenceList *L,int i, char x)
{
int j;
if(L->size >= 100)
{
printf("顺序表已满\n");
return 0;
}
else if (i<0 || i>L->size)
{
printf("不合法");
return 0;
}
else
{
for(j=L->size;j>i;j--)
L->list[j]=L->list[j-1];
L->list[i]=x;
L->size ++;
return 1;
}
}
int ListLength(SequenceList L)
{
return L.size;
}
typedef struct
{
SequenceList Vertices;
int edge[100][100];
int numOfEdges;
}MatrixGraph;
void Initiate(MatrixGraph *G,int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
G->edge[i][j]=0;
}
}
G->numOfEdges=0;
ListInitiate(&G->Vertices) ;
}
void InsertVertex(MatrixGraph *G,int vertex)
{
ListInsert(&G->Vertices,G->Vertices.size,vertex);
}
void InsertEdge(MatrixGraph *G,int v1,int v2)
{
if(v1<0||v1>=G->Vertices.size||v2<0||v2>=G->Vertices.size)
{
printf("参数错误");
exit(1);
}
G->edge[v1][v2]=1;
G->edge[v2][v1]=1;
G->numOfEdges++;
}
typedef struct
{
int row,col;
}RowCol;
void CreatGraph(MatrixGraph *G,int V[],int n,RowCol E[],int e)
{
int i,k;
Initiate(G,n);
for(i=0;i<n;i++)
InsertVertex(G,V[i]);
for(k=0;k<e;k++)
InsertEdge(G,E[k].row,E[k].col);
}
int visit_dfs[100];
void dfs(MatrixGraph G,int i)
{
int j;
visit_dfs[i]=1;
printf("%c ",G.Vertices.list[i]);
for(j=0;j<G.numOfEdges ;j++)
{
if(G.edge [i][j]==1&&!visit_dfs[j])
dfs(G,j);
}
}
void dfstraverse(MatrixGraph G)
{
int i;
for(i=0;i<G.numOfEdges ;i++)
{
visit_dfs[i]=0;
}
for(i=0;i<G.numOfEdges ;i++)
{
if(!visit_dfs[i])
dfs(G,i);
}
}
typedef struct Qnode
{
int data;
struct Qnode *next;
}Qnode, *Qptr; //定义节点
typedef struct LINKQUEUE
{
Qptr front;
Qptr rear;
}LinkQueue; //定义队首、队尾指针
void InitQueue(LinkQueue *q) //队列初始化
{
//定义头结点,队首队尾都指向头结点
Qptr firstnode = (Qptr)malloc(sizeof(Qnode));
q->front = q->rear = firstnode;
if (!q->front)
{
exit(0);
}
q->front->next = NULL;
}
void PushQueue(LinkQueue *q, int e)
{
//在队尾插入元素
Qptr p = (Qptr)malloc(sizeof(Qnode));
if (!p)
{
exit(0);
}
p->data = e;
p->next = NULL;
q->rear->next = p;
q->rear = p;
}
void DetQueue(LinkQueue *q, int e)
{
//出队列在队首进行
if (q->front == q->rear)
{
printf("队列中无元素!\n");
exit(0);
}
Qptr p = q->front->next;
e = p->data;
q->front->next = p->next;
if (q->rear == p)
{
q->rear = q->front;
}
free(p);
}
//检验是否为空
int QueueEmpty(LinkQueue *q)
{
if (q->front == q->rear)
return 0;
else
return 1;
}
int visited[100];
void BFSTraverse(MatrixGraph G)
{
int k;
int i,j;
LinkQueue Q;
InitQueue(&Q);
for (i = 0; i < G.numOfEdges ; i++)
{
visited[i] = 0; //初始化标记数组
}
for (i = 0; i < G.numOfEdges ; i++)
{
if (!visited[i])
{
visited[i] = 1;
printf("%c ", G.Vertices .list[i]);
PushQueue(&Q, i);
}
while (!QueueEmpty(&Q))
{
DetQueue(&Q, k);
for ( j = 0; j < G.numOfEdges ; j++)
{
if (G.edge [k][j] == 1 && !visited[j])
{
visited[j] = 1;
printf("%c", G.Vertices .list[j]);
PushQueue(&Q, j);
}
}
}
}
}
主函数
#include<stdio.h>
#include<stdlib.h>
#include"MGraph.h"
void main()
{
MatrixGraph g1;
int a[]={'1','2','3','4','5'};
RowCol rc[]={{0,1},{0,2},{0,3},{0,4},{1,3},{2,4}};
int n=5,e=6;
int i,j;
CreatGraph(&g1,a,n,rc,e);
printf("顶点集合为:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("%c ",g1.Vertices.list[i]);
printf("\n");
printf("邻接矩阵为:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("%5c",g1.Vertices.list[i]);
printf("\n\n");
for(i=0;i<g1.Vertices.size;i++)
{
printf("%d",i+1);
for(j=0;j<g1.Vertices.size;j++)
printf("%5d",g1.edge[i][j]);
printf("\n");
}
printf("深度优先遍历:\n");
dfstraverse(g1);
printf("\n广度优先遍历:\n");
BFSTraverse(g1);
}
选做题
头文件
typedef struct
{
int list[100];
int size;
}SequenceList;
int ListInitiate(SequenceList *L)
{
L->size = 0;
}
int ListInsert(SequenceList *L,int i, char x)
{
int j;
if(L->size >= 100)
{
printf("顺序表已满\n");
return 0;
}
else if (i<0 || i>L->size)
{
printf("不合法");
return 0;
}
else
{
for(j=L->size;j>i;j--)
L->list[j]=L->list[j-1];
L->list[i]=x;
L->size ++;
return 1;
}
}
int ListLength(SequenceList L)
{
return L.size;
}
typedef struct
{
SequenceList Vertices;
int edge[100][100];
int numOfEdges;
}MatrixGraph;
void Initiate(MatrixGraph *G,int n)
{
int i,j;
for(i=0;i<n;i++)
{
for(j=0;j<n;j++)
{
if(i==j)
G->edge[i][j]=0;
else
G->edge [i][j]=666;
}
}
G->numOfEdges=0;
ListInitiate(&G->Vertices) ;
}
void InsertVertex(MatrixGraph *G,int vertex)
{
ListInsert(&G->Vertices,G->Vertices.size,vertex);
}
void InsertEdge(MatrixGraph *G,int v1,int v2,int w)
{
if(v1<0||v1>=G->Vertices.size||v2<0||v2>=G->Vertices.size)
{
printf("参数错误");
exit(1);
}
G->edge[v1][v2]=w;
G->numOfEdges++;
}
typedef struct
{
int row,col,w;
}RowCol;
void CreatGraph(MatrixGraph *G,int V[],int n,RowCol E[],int e)
{
int i,k;
Initiate(G,n);
for(i=0;i<n;i++)
InsertVertex(G,V[i]);
for(k=0;k<e;k++)
InsertEdge(G,E[k].row,E[k].col,E[k].w);
}
主函数
#include<stdio.h>
#include<stdlib.h>
#include"mmm.h"
void dijkstra(MatrixGraph G,int V0,int *sn,int *sw)
{
int v,w,k,min;
int final[G.Vertices.size];//标志数组,若顶点Vi最短路径已知,则final[i]=1;
for(v=0;v<G.Vertices.size;v++){
final[v]=0;
sn[v]=0;
sw[v]=G.edge[V0][v];
}
sw[V0]=0;
final[V0]=1;
//初始化完成,主循环开始
for(v=1;v<G.Vertices.size;v++)
{ //每次循环确定V0到一个顶点的最短路径
min=666; //初始化最小值min
for(w=0;w<G.Vertices.size;w++)
{ //遍历寻找离V0最近的点
if(!final[w]&&sw[w]<min)
{ //如果Vw的最短路径还没找到且w到V0的权值比min小
k=w; //k存储离V0最近的点的下边
min=sw[w];
//那么顶点Vw离V0更近
}
}
final[k]=1; //Vk是离V0最近的点,则Vk的最短路径已经找到,所以标志改为1
for(w=0;w<G.Vertices.size;w++){
if(!final[w]&&(min+G.edge[k][w])<sw[w]){
//如果顶点Vw的最短路径未确定且经过VK的路径比V0直达的路径短的话
sw[w]=min+G.edge[k][w];
sn[w]=k; //经过Vk的路径更短,则其前驱下标为k
}
}
}
sn[0]=-1;
}
void prin(int n ,int *sn)
{
int a[10]={0},i=1,j=n,q=0;
a[0]=n;
while(1)
{
if(sn[j]==-1)
break;
a[i]=sn[j];
j=a[i];
i++;
}
q=i;
for(i=q-1;i>-1;i--)
printf("%c ",a[i]+65);
}
void main()
{
MatrixGraph g1;
int a[]={'A','B','C','D','E','F'};
RowCol rc[]={{0,2,5},{0,3,30},{1,0,2},{1,4,8},{2,1,15},{2,5,7},{4,3,4},{5,3,10},{5,4,18}};
int n=6,e=9;
int i,j;
CreatGraph(&g1,a,n,rc,e);
printf("顶点集合为:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("%c ",g1.Vertices.list[i]);
printf("\n");
printf("邻接矩阵为:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("%5c",g1.Vertices.list[i]);
printf("\n\n");
for(i=0;i<g1.Vertices.size;i++)
{
printf("%c",65+i);
for(j=0;j<g1.Vertices.size;j++)
printf("%5d",g1.edge[i][j]);
printf("\n");
}
int sn[100],v0=0;
int sw[100];
dijkstra(g1,v0,sn,sw);
printf("从顶点A到其他各项顶点的最短距离为:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("到顶点%c的最短距离为%d\n",65+i,sw[i]);
printf("path数组:\n");
for(i=0;i<g1.Vertices.size;i++)
printf("%d ",sn[i]);
printf("\n");
printf("A到其他点的最短路:\n");
for(i=1;i<g1.Vertices.size;i++)
{
prin(i,sn);
printf("\n");
}
}