实验目的:掌握图的邻接矩阵和邻接表两个存储结构及表示。
掌握图的DFS和BFS两种遍历算法。
理解并掌握下述完整算法的基本思想以及算法实现方法:最小生成树算法、最短路径算法、拓扑排序算法及关键路径算法。
实验内容:1. 创建一个无向图,并分别对其进行DFS和BFS。
2. 实现最短路径、最小生成树、拓扑排序三种算法。
#include<stdio.h>
#include<string.h>
#include<windows.h>
#define MAX 100
#include<malloc.h>
int vis[MAX],map[MAX][MAX];
int du[MAX];
typedef struct
{
<span style="white-space:pre"> </span>char vex[MAX];//顶点信息
<span style="white-space:pre"> </span>int edge[MAX][MAX];//邻接矩阵
<span style="white-space:pre"> </span>int n,e;//图中当前顶点数和边数
}graph;
typedef char VertexType; //顶点类型
typedef struct node //边表节点
{
int adjvex; //邻接点域
node* next; //链域
}EdgeNode;
typedef struct //顶点表节点
{
VertexType vertex; //顶点域
EdgeNode* firstedge; //边表头指针
}VertexNode;
typedef VertexNode AdjList[MAX];//AdjList是邻接表类型
typedef struct
{
AdjList adjlist; //邻接表
int n,e; //当前图中顶点数与边数
}ALGraph;
typedef struct Lnode
{ int data;<span style="white-space:pre"> </span>//队列元素<span style="white-space:pre"> </span>
struct Lnode *next;<span style="white-space:pre"> </span>
}Lnode, *QueuePtr;
typedef struct{
<span style="white-space:pre"> </span>QueuePtr front;
<span style="white-space:pre"> </span>QueuePtr rear;
}LinkQueue;
void InitQueue(LinkQueue *q)//生成队列
{q->front=q->rear=(QueuePtr)malloc(sizeof(Lnode));
q->front->next=NULL;
}
void EnQueue(LinkQueue *q, int e)//向队列中添加元素
{
QueuePtr p;
p=(QueuePtr)malloc(sizeof(Lnode));
p->data=e;
p->next=NULL;
q->rear->next=p;
q->rear=p;
}
int DeQueue(LinkQueue *q)//输出队列头元素
{
return q->front->next->data;
QueuePtr p;
if(q->front==q->rear)
{
printf("\nqueue is empty\n");
return ERROR;
}
p=q->front->next;
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 1;
else return 0;}
void create(ALGraph *L) //建立邻接表
{
int i,j,k,w,v;
EdgeNode *s;
printf("读入顶点数和边数");
scanf("%d%d",&L->n,&L->e);
printf("建立顶点表");
<span style="white-space:pre"> </span> getchar();
for (i=0;i<L->n;i++)
{
scanf("%c",&L->adjlist[i].vertex);
L->adjlist[i].firstedge=NULL;
}
printf("建立边表\n");
for (k=0;k<L->e;k++)
{
printf("读入(vi-vj)的顶点对序号");
scanf("%d%d",&i,&j);
s=(EdgeNode*)malloc(sizeof(EdgeNode));
s->adjvex=j;
s->next=L->adjlist[i].firstedge; //插入表头
L->adjlist[i].firstedge=s;
s=(EdgeNode*)malloc(sizeof(EdgeNode));
s->adjvex=i;
s->next=L->adjlist[j].firstedge;
L->adjlist[j].firstedge=s;
}
}
void shuchu(ALGraph *L)//输出邻接表
{
<span style="white-space:pre"> </span>int i;
<span style="white-space:pre"> </span>printf("%d ",L->n);
for(i=0;i<L->n;i++)
{
printf("%d->",i);
while(L->adjlist[i].firstedge!=NULL)
{
printf("%d->",L->adjlist[i].firstedge->adjvex);
L->adjlist[i].firstedge=L->adjlist[i].firstedge->next;
}
printf("\n");
}
}
void creat1(graph *G)//构建邻接矩阵
{
<span style="white-space:pre"> </span>int i,j,k,w;
<span style="white-space:pre"> </span>char ch;
<span style="white-space:pre"> </span>printf("输入顶点数与边数\n");
<span style="white-space:pre"> </span>scanf("%d%d",&G->n,&G->e);
<span style="white-space:pre"> </span>printf("输入顶点信息\n");
<span style="white-space:pre"> </span>scanf("%s",G->vex);
<span style="white-space:pre"> </span>for(i=0;i<G->n;i++)
<span style="white-space:pre"> </span>for(j=0;j<G->n;j++)
<span style="white-space:pre"> </span>G->edge[i][j]=1000000;
<span style="white-space:pre"> </span>printf("输入边的信息\n");
<span style="white-space:pre"> </span>for(k=0;k<G->e;k++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d%d",&i,&j,&w);
<span style="white-space:pre"> </span>G->edge[i][j]=w;
<span style="white-space:pre"> </span>G->edge[j][i]=w;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("构建成功!\n");
}
void DFS(graph *G,int i)//DFS深搜
{
<span style="white-space:pre"> </span>int j;
<span style="white-space:pre"> </span>printf("visit vertex:%c\n",G->vex[i]);
<span style="white-space:pre"> </span>vis[i]=1;
<span style="white-space:pre"> </span>for(j=0;j<G->n;j++)
<span style="white-space:pre"> </span>if(G->edge[i][j]!=0&&!vis[j])
<span style="white-space:pre"> </span>DFS(G,j);
<span style="white-space:pre"> </span>
}
void BFS(graph *G,int k)//BFS广搜
{
<span style="white-space:pre"> </span>int i,j;
<span style="white-space:pre"> </span>LinkQueue q;
<span style="white-space:pre"> </span>InitQueue(&q);
<span style="white-space:pre"> </span>printf("visit vertex:%c\n",G->vex[k]);
<span style="white-space:pre"> </span>vis[k]=1;
<span style="white-space:pre"> </span>EnQueue(&q,k);
<span style="white-space:pre"> </span>while(!QueueEmpty(&q))
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>i=DeQueue(&q);
<span style="white-space:pre"> </span>for(j=0;j<G->n;j++)
<span style="white-space:pre"> </span>if(G->edge[i][j]!=0&&!vis[j])
<span style="white-space:pre"> </span>BFS(G,j);
<span style="white-space:pre"> </span>}
}
void prim(graph *G,int u)//prim最小生成数
{
<span style="white-space:pre"> </span>int i,j,pos,min,result=0;
<span style="white-space:pre"> </span>int low[MAX];
for(i=0;i<=G->n;i++)
vis[i]=0;
//从某点开始,分别标记和记录该点
vis[u]=1;
pos=u;
low[u]=0;
//第一次给low数组赋值
for(i=0;i<G->n;i++)
if(i!=pos)
low[i]=G->edge[pos][i];
//再运行n-1次
for(i=1;i<G->n;i++)
{
//找出最小权值并记录位置
min=100000;
for(j=0;j<G->n;j++)
if(vis[j]==0&&min>low[j])
{
min=low[j];
pos=j;
}
//最小权值累加
result+=min;
//标记该点
vis[pos]=1;
//更新权值
for(j=0;j<G->n;j++)
if(vis[j]==0&&low[j]>G->edge[pos][j])
low[j]=G->edge[pos][j];
}
printf("以%d开始的最小生成树长度为:%d\n ",u,result);
}
void floyd(graph *G)//最短路径
{
<span style="white-space:pre"> </span>int i,j,k;
<span style="white-space:pre"> </span>for(i =0;i<G->n;i++)
<span style="white-space:pre"> </span>for(j=0;j<G->n;j++)
<span style="white-space:pre"> </span>map[i][j]=G->edge[i][j];
<span style="white-space:pre"> </span>for(k=0;k<G->n;k++)
<span style="white-space:pre"> </span>for(i=0;i<G->n;i++)
<span style="white-space:pre"> </span>for(j=0;j<G->n;j++)
<span style="white-space:pre"> </span>if(map[i][j]>map[i][k]+map[k][j])
<span style="white-space:pre"> </span>map[j][i]=map[i][j]=map[i][k]+map[k][j];
<span style="white-space:pre"> </span>int n,m;
<span style="white-space:pre"> </span>char a,b;
<span style="white-space:pre"> </span>getchar();
<span style="white-space:pre"> </span>printf("请输入要查询两点距离:");
<span style="white-space:pre"> </span>scanf("%c %c",&a,&b);
<span style="white-space:pre"> </span>for(i=0;i<G->n;i++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>if(G->vex[i]==a)
<span style="white-space:pre"> </span>n=i;
<span style="white-space:pre"> </span>if(G->vex[i]=b)
<span style="white-space:pre"> </span>m=i;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>if(map[m][n]>=100000)
<span style="white-space:pre"> </span>printf("两点之间无最短距离\n");
<span style="white-space:pre"> </span>else
<span style="white-space:pre"> </span>printf("两点间最短距离为%d\n",map[n][m]);
<span style="white-space:pre"> </span>
}
void jiemian1()
{
<span style="white-space:pre"> </span>printf("\t\t\t目录\n");
printf("\t\t1、邻接矩阵\n");
<span style="white-space:pre"> </span>printf("\t\t2、邻接表\n");
<span style="white-space:pre"> </span>printf("\t\t3、退出\n");
<span style="white-space:pre"> </span>printf("\t\t请输入操作选项: ");
}
void jiemian2()
{ printf("\t\t\t目录\n");
<span style="white-space:pre"> </span>printf("\t\t1、创建无向图\n");
<span style="white-space:pre"> </span>printf("\t\t2、DFS搜索\n");
<span style="white-space:pre"> </span>printf("\t\t3、BFS搜索\n");
<span style="white-space:pre"> </span>printf("\t\t4、最短路径\n");
<span style="white-space:pre"> </span>printf("\t\t5、最小生成树\n");
<span style="white-space:pre"> </span>printf("\t\t6、拓扑排序\n");
<span style="white-space:pre"> </span>printf("\t\t7、退出\n");
<span style="white-space:pre"> </span>
}
void init(graph *G)
{ int i;
<span style="white-space:pre"> </span>for(i=0;i<G->n;i++)
<span style="white-space:pre"> </span>vis[i]=0;
}
void topu(graph *G)
{
printf("构成一个有向图\n");
int i,j,k;
<span style="white-space:pre"> </span>char ch;
<span style="white-space:pre"> </span>printf("输入顶点数与边数\n");
<span style="white-space:pre"> </span>scanf("%d%d",&G->n,&G->e);
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>printf("输入顶点信息\n");
<span style="white-space:pre"> </span>getchar();
for(i=0;i<G->n;i++)
<span style="white-space:pre"> </span>scanf("%c",&G->vex[i]);
<span style="white-space:pre"> </span>for(i=0;i<=G->n;i++)
<span style="white-space:pre"> </span>du[i]=0;
<span style="white-space:pre"> </span>for(i=0;i<=G->n;i++)
<span style="white-space:pre"> </span>for(j=0;j<=G->n;j++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>G->edge[i][j]=0;
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("输入边的信息\n");
<span style="white-space:pre"> </span>for(k=0;k<G->e;k++)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>scanf("%d%d",&i,&j);
<span style="white-space:pre"> </span>G->edge[i][j]=G->edge[j][i]=1;
<span style="white-space:pre"> </span>du[j]++;
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
<span style="white-space:pre"> </span>printf("构建成功!\n");
printf("拓扑排序结果如下:\n");
for(j=0;j<G->n;j++)
{
for(i=0;i<G->n;i++)
{
<span style="white-space:pre"> </span>if(du[i]==0)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>du[i]=-1;
<span style="white-space:pre"> </span>k=i;
<span style="white-space:pre"> </span>printf("%c ",G->vex[i]);
<span style="white-space:pre"> </span>break;<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>}
}
for(i=0;i<=G->n;i++)
{
<span style="white-space:pre"> </span>if(G->edge[k][i]==1)
<span style="white-space:pre"> </span>du[i]--;
}<span style="white-space:pre"> </span>
}
}
int main()
{
ALGraph *L;
graph *G;
while(1)
{
<span style="white-space:pre"> </span>int n;
<span style="white-space:pre"> </span>jiemian1();
<span style="white-space:pre"> </span>scanf("%d",&n);
<span style="white-space:pre"> </span>if(n==1)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> system("cls");
<span style="white-space:pre"> </span> G=(graph*)malloc(sizeof(graph));
<span style="white-space:pre"> </span>int m;
<span style="white-space:pre"> </span>jiemian2();
<span style="white-space:pre"> </span>while(1)
<span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span>printf("\t\t请输入操作选项;");
<span style="white-space:pre"> </span> scanf("%d",&m);
<span style="white-space:pre"> </span> switch(m)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 1:creat1(G);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 2:init(G),DFS(G,0);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 3:init(G),BFS(G,0);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 4:init(G),prim(G,0);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 5:init(G),floyd(G);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 6:topu(G);break;
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>case 7:return 0;
<span style="white-space:pre"> </span> }<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span>
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> else if(n==2)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>system("cls");
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>L= (ALGraph*)malloc(sizeof(ALGraph));
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>printf("1、建立无向图\n");
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>printf("2、输出无向图\n");
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>printf("3、退出\n");
<span style="white-space:pre"> </span> int m;
<span style="white-space:pre"> </span> while(1)
<span style="white-space:pre"> </span> {
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>printf("输入选择:");
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>scanf("%d",&m);
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>switch(m)
<span style="white-space:pre"> </span> <span style="white-space:pre"> </span>{
<span style="white-space:pre"> </span> case 1:create(L);break;
<span style="white-space:pre"> </span> case 2:shuchu(L);break;
<span style="white-space:pre"> </span> case 3:return 0;
<span style="white-space:pre"> </span> }
<span style="white-space:pre"> </span> printf("%d ",L->n);
}
}
<span style="white-space:pre"> </span>else
<span style="white-space:pre"> </span>return 0;
}
}