编程随机生成含m个结点和n条边的无向简单图并能进行(半)欧拉图的判定,若是则给出欧拉(回)路。
实验要求如下:
具体实现思路可以参考下面:
因为如果我们使用局部变量,每一个函数都会使用这些变量,会让函数的参数越变越多。
所以我们将这些变量定义为全局变量,这样就不用在参数中调用了。
#define MAX 100
int arrMap[MAX][MAX] = { 0 };//图的矩阵
int degree[MAX] = { 0 };//节点的度
int visit[MAX] = { 0 };//记录是否被访问
int euler[MAX] = { -1 };
int ans[MAX]; //欧拉路
int c[MAX][MAX]; //判断该边是否已经走过
int m = 0;//结点个数
int n = 0;//边数
//随机生成边
void creatSide()
{
int count = 0;
while (count < n)
{
int x = rand() % m;
int y = rand() % m;
while (x == y)
x = rand() % m;
if (!arrMap[x][y])
{
arrMap[x][y] = arrMap[y][x] = 1;
count++;
degree[x]++;
degree[y]++;
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", arrMap[i][j]);
}
printf("\n");
}
}
//深度优先搜索判断是否为连通图
void DFS(int x)
{
visit[x] = 1;
for (int i = 0; i < m; i++)
{
if (!visit[i] && arrMap[x][i])
{
DFS(i);
}
}
}
//判断联通是返回1不是返回0
int judgeConnect()
{
DFS(0);
for (int i = 0; i < m; i++)
{
if (!visit[i])
{
return 0;
}
}
return 1;
}
有0个或2个奇数度结点的有欧拉路,通过遍历记录度的数组看奇数度节点的个数。
//判断是否是(半)欧拉图
void judgeEuler()
{
int first = 0;
int num = 0;//奇数结点个数
for (int i = 0; i < m; i++)
{
if (degree[i] % 2 != 0)
{
first = i;
num++;
}
}
if (num == 1 || num > 2)
{
printf("不是欧拉图或半欧拉图\n");
}
else
{
euler[0]= first;
trav(first, 1);
if (num == 0)
{
printf("随机生成的图是欧拉图\n");
printf("该欧拉图的一条欧拉路是\n");
}
else
{
printf("随机生成的图是半欧拉图\n");
printf("该半欧拉图的一条欧拉路是\n");
}
for (int i = 0; i < n; i++)
{
printf("%d->", ans[i]);
}
printf("%d\n", ans[n]);
}
}
//找欧拉路
void trav(int p, int q)
{
int flag = 1;
if (euler[n] != -1)
{
if(flag == 1)
{
for (int i = 0; i <= n; i++)
{
ans[i] = euler[i];
}
flag = 0;
}
}
for (int i = 0; i < m; i++)
{
if (arrMap[p][i] && !c[p][i])
{
euler[q] = i;
c[p][i] = c[i][p] = 1;
trav(i, q + 1);
if (!flag)return;
else c[p][i] = c[i][p] = 0;
}
}
}
源码如下:
# define _CRT_SECURE_NO_WARNINGS 1;
#include
#include
#include
#define MAX 100
int arrMap[MAX][MAX] = { 0 };//图的矩阵
int degree[MAX] = { 0 };//节点的度
int visit[MAX] = { 0 };//记录是否被访问
int euler[MAX] = { -1 };
int ans[MAX]; //欧拉路
int c[MAX][MAX]; //判断该边是否已经走过
int m = 0;//结点个数
int n = 0;//边数
//随机生成边
void creatSide()
{
int count = 0;
while (count < n)
{
int x = rand() % m;
int y = rand() % m;
while (x == y)
x = rand() % m;
if (!arrMap[x][y])
{
arrMap[x][y] = arrMap[y][x] = 1;
count++;
degree[x]++;
degree[y]++;
}
}
for (int i = 0; i < m; i++)
{
for (int j = 0; j < m; j++)
{
printf("%d ", arrMap[i][j]);
}
printf("\n");
}
}
//深度优先搜索判断是否为连通图
void DFS(int x)
{
visit[x] = 1;
for (int i = 0; i < m; i++)
{
if (!visit[i] && arrMap[x][i])
{
DFS(i);
}
}
}
//判断联通是返回1不是返回0
int judgeConnect()
{
DFS(0);
for (int i = 0; i < m; i++)
{
if (!visit[i])
{
return 0;
}
}
return 1;
}
//找欧拉路
void trav(int p, int q)
{
int flag = 1;
if (euler[n] != -1)
{
if(flag == 1)
{
for (int i = 0; i <= n; i++)
{
ans[i] = euler[i];
}
flag = 0;
}
}
for (int i = 0; i < m; i++)
{
if (arrMap[p][i] && !c[p][i])
{
euler[q] = i;
c[p][i] = c[i][p] = 1;
trav(i, q + 1);
if (!flag)return;
else c[p][i] = c[i][p] = 0;
}
}
}
//判断是否是(半)欧拉图
void judgeEuler()
{
int first = 0;
int num = 0;//奇数结点个数
for (int i = 0; i < m; i++)
{
if (degree[i] % 2 != 0)
{
first = i;
num++;
}
}
if (num == 1 || num > 2)
{
printf("不是欧拉图或半欧拉图\n");
}
else
{
euler[0]= first;
trav(first, 1);
if (num == 0)
{
printf("随机生成的图是欧拉图\n");
printf("该欧拉图的一条欧拉路是\n");
}
else
{
printf("随机生成的图是半欧拉图\n");
printf("该半欧拉图的一条欧拉路是\n");
}
for (int i = 0; i < n; i++)
{
printf("%d->", ans[i]);
}
printf("%d\n", ans[n]);
}
}
int main()
{
srand((unsigned int)time(NULL));
printf("请输入结点个数:");
scanf("%d", &m);
printf("请输入边数,需小于等于%d:", m * (m - 1) / 2);
scanf("%d", &n);
back:
creatSide();
int ret = judgeConnect();
if (ret == 0)
{
printf("该图不是连通图,结点度为\n");
for (int i = 0; i < m; i++)
{
printf("%d ", degree[i]);
}
printf("\n");
goto back;
}
else
{
judgeEuler();
}
return 0;
}