数据结构实验十二 图的遍历及应用
一、【实验目的】
1、 理解图的存储结构与基本操作;
2、熟悉图的深度度优先遍历和广度优先遍历算法
3、掌握图的单源最短路径算法
二、【实验内容】
1.根据下图(图见实验11)邻接矩阵,编程实现该图的深度与广度优先遍历算法,输出遍历序列。
2.单源节点最短路径问题
问题描述:求从有向图的某一结点出发到其余各结点的最短路径。
基本要求:
(1)有向图采用邻接矩阵表示。
(2)单源节点最短路径问题采用Dijkstra算法。
(3)输出有向图中从源结点T到其余各结点的最短路径和最短路径值。
三、实验源代码
#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#define Max 100
int n;
int book[100] = { 0 };
typedef int ElemType;
typedef struct {
int a[100][100];
int numofvex;
char list[100];
}Matrix;
typedef struct {
int front, rear, top;
ElemType queue[Max];
}Q;
Q* qinit()
{
Q* q;
q = (Q*)malloc(sizeof(Q));
q->front = q->rear = q->top = 0;
return q;
}
int notempty(Q* q)//返回0即为空
{
if (q->rear == q->front && q->top == 0)
return 0;
return 1;
}
void qappend(Q* q, int v)
{
if (q->top > Max)
{
printf("out of space");
return;
}
q->queue[q->rear] = v;
q->rear = (q->rear + 1) % Max;
q->top++;
}
void qdelete(Q* q, int *v)
{
if (q->top == 0)
{
printf("lack of element");
return;
}
*v = q->queue[q->front];
q->front = (q->front + 1) % Max;
q->top--;
}
Matrix* init()
{
int i, j;
Matrix* my = (Matrix*)malloc(sizeof(Matrix));
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
{
if (i == j)
my->a[i][j] = 0;
else
my->a[i][j] = Max;
}
for (i = 0; i < n; i++)
my->list[i] = i + 'A';
my->numofvex = n;
return my;
}
Matrix* create()
{
char d, z;
int i, j, w;
Matrix* my= init();
i = j = w = 0;
printf("请以三元组形式输入\n");
getchar();
while (1)
{
scanf("%c %c %d", &z,&d,&w);
getchar();
i = z - 'A';
j = d - 'A';
my->a[i][j] = w;
if (w == 0&&z=='0'&&d=='0')
break;
}
return my;
}
int getfirstvex(int v, Matrix* my)
{
int i;
for (i = 0; i < n; i++)
if (my->a[v][i] > 0 && my->a[v][i] < Max)
return i;
return -1;
}
int getnextvex(int u, int v, Matrix* my)
{
int i;
for (i = v + 1; i < n; i++)
if (my->a[u][i] > 0 && my->a[u][i] < Max)
return i;
return -1;
}
void dfs(int v, Matrix* my)
{
int w;
book[v] = 1;
printf("%c ", my->list[v]);
w = getfirstvex(v, my);
while (w != -1)
{
if (!book[w])
dfs(w, my);
w = getnextvex(v, w, my);
}
}
void bfs(int v, Matrix* my)
{
Q* q;
q = qinit();
int w;
qappend(q, v);
book[v] = 1;
while (notempty(q))
{
qdelete(q, &v);
printf("%c ", my->list[v]);
w = getfirstvex(v, my);
while (w != -1)
{
if (!book[w])
{
book[w] = 1;
qappend(q, w);
}
w = getnextvex(v, w, my);
}
}
}
void Dijkstra(int v, Matrix* my,int distance1[],int path[])//赋值path[]与distance1[],v为出发点
{
int i, j,wmin=Max,x=0;
int* s = (int*)malloc(sizeof(int) * n);//定义访问数组s[]
for (i = 0; i < n; i++)//初始化path[],distance1[]
{
s[i] = 0;
distance1[i] = my->a[v][i];
if (my->a[v][i] != Max&& my->a[v][i] != 0&&i!=v)//能直接到达的点进行初步赋值
{
path[i] = v;
}
else//不能到达即自旋,和无路径
{
path[i] = -1;
}
}
s[v] = 1;
for (x = 1; x < n; x++)//已经访问过一个点所以还剩n-1个点未访问
{
wmin = Max;
for (i = 0; i < n; i++)//找最小权值,且未被访问过
{
if (distance1[i] < wmin&&s[i]!=1)
{
j = i;
wmin = distance1[i];
}
}
if (wmin == Max)//非连通图总有一个无法到达故距离为Max应该及时退出
return;
s[j] = 1;
for (i = 0; i < n; i++)//看看对distance[]是否有影响,更新
{
if (s[i] == 0 && my->a[j][i] > 0 && my->a[j][i] != Max && distance1[i] > distance1[j] + my->a[j][i])
{
distance1[i] = distance1[j] + my->a[j][i];
path[i] = j;
}
}
}
}
void print(int m,int v,Matrix*my,int path[])
{
int x = 0;
char ch[100];
if (v == -1)
printf("%c ", my->list[m]);
else
{
while (v != -1)
{
ch[x] = my->list[v];
v = path[v];
x++;
}
for (int i = x - 1; i >= 0; i--)
printf("%c", ch[i]);
printf(" ");
}
}
void reset(int* a)
{
for (int i = 0; i < n; i++)
a[i] = 0;
}
int main()
{
Matrix* my ;
int path[100];
int distance1[100] = { 0 };
char c;
int i, j;
printf("请输入节点个数:");
scanf("%d", &n);
my=create();
printf("邻接矩阵为:\n");
for (i = 0; i < n; i++)
{
for (j = 0; j < n; j++)
printf("%d ", my->a[i][j]);
printf("\n");
}
printf("请输入从哪一个节点开始进行深度优先遍历搜索:");
scanf("%c", &c);
dfs(c-'A', my);
getchar();
printf("\n");
reset(book);
printf("请输入从哪一个节点开始进行广度优先遍历搜索:");
scanf("%c", &c);
bfs(c-'A', my);
printf("\n");
getchar();
printf("请输入哪一个节点到其他节点的最短路径:");
scanf("%c", &c);
Dijkstra(c - 'A', my,distance1,path);
printf("path[]数组:");
for (i = 0; i < n; i++)
printf("%d ", path[i]);
printf("\n");
printf("点%c到其他点的最小路径 最小路径权值为\n",c);
for ( i = 0; i < n; i++)
{
print(c-'A',i, my, path);
printf("%d\n", distance1[i]);
}
}
四、实验结果
五、实验总结
使用scanf()前应当消除’\n’和’ ‘。来确保输入的准确性