离散数学实验报告 实验3 欧拉路的确定

离散数学实验报告 实验3 欧拉路的确定

一、实验目的
理解欧拉图的概念,掌握欧拉通/回路的判定方法。
二、实验内容
输入一个无向简单图的邻接矩阵,判定该图是否含有欧拉通/回路。若有,请给出一条欧拉通/回路。
三、实验环境
采用C或C++语言为编程语言实现。
四、实验过程

  1. 算法分析
    (1) 无向图G是欧拉图当且仅当G是连通的且没有奇度顶点。
    (2) 无向图G是半欧拉图当且仅当G是连通的且恰有两个奇度顶点。
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
#include<string.h>
#define N 100

struct stacks
{
	int top;
	int node[100];
}s;

int n, a[N][N],b[N];
bool visit[N];
int ans[N], cnt = 0; //记录欧拉路的路径,路径数
void show();
void DFS(int);
bool judge_connect();       //判断是否连通  
void judge_euler();     //判断是否是欧拉回路 
void Fleury(int x);
void answer();

int main()
{
	
		memset(a, 0, sizeof(a));
		//memset(ans, 0, sizeof(ans));//使用循环可使用次代码重置数组为0
		printf("请输入顶点个数(小于等于100):\n");
		scanf_s("%d", &n);
		if (n < 0 || n>100)
		{
			printf("请输入小于等于100的数!\n");
			exit(0);
		}
		for (int i = 0; i < n; i++)
			for (int j = i + 1; j < n; j++)
			{
				a[i][j] = 0 + rand() % 2; //随机生成无向图
				a[j][i] = a[i][j];
			}
		show();
		if (judge_connect())
		{
			printf("该随机生成的图是连通图\n");
			judge_euler();

		}
		else
		{
			printf("该随机生成的图不是连通图\n");

		}
	return 0;
}


void DFS(int x)
{
	visit[x] = true;
	for (int i = 0; i < n; i++)
		if (!visit[i] && a[x][i])
			DFS(i);
}
bool judge_connect()
{
	DFS(0);
	for (int i = 0; i < n; i++)
		if (!visit[i])
			return false;
	return true;
}
void judge_euler()
{
	int num = 0, start = 0, degree; // 奇度顶点个数, 欧拉路的起点, 每个顶点的度
	//如果存在奇度顶点,则从奇度顶点出发,否则从0出发
	for (int i = 0; i < n; i++)
	{
		degree = 0;
		for (int j = 0; j < n; j++)
			degree += a[i][j];
		if (degree % 2)
		{
			start = i;
			num++;
		}
	}

	//无向图具有一条欧拉路,当且仅当G是连通的,且有0个或2个奇数度结点
	if (num == 0 || num == 2)
	{			
		Fleury(start);
		//欧拉路径的头和尾相等,则说明欧拉路是回路
		if (ans[0] == ans[cnt - 1])
			printf( "该图为欧拉图,欧拉回路为: ");
		else
			printf ( "该图为半欧拉图,欧拉通路为: ");
		answer();			
	}
	else
	{
		printf("非(半)欧拉图\n");
	}
}
void DFS2(int x) //深度优先遍历
{
	s.top++;
	s.node[s.top] = x;
	for (int i = 0; i < n; i++)
	{
		if (a[i][x] > 0)
		{
			a[i][x] = 0; //删边操作
			a[x][i] = 0;
			DFS2(i);
			break;
		}
	}
}
void Fleury(int x)  //Fleury算法
{
	int b;
	s.top = 0;
	s.node[s.top] = x; //起点入栈
	while (s.top >= 0)
	{
		b = 0;
		for (int i = 0; i < n; i++)
		{
			if (a[s.node[s.top]][i] > 0)
			{
				b = 1;
				break;
			}
		}
		if (b == 0) //如果没有可扩展的点,则记录下该点并将其出栈
		{
			ans[cnt++] = s.node[s.top] + 1;
			s.top--;
		}
		else //如果有,则将其出栈并继续搜索
		{
			s.top--;
			DFS2(s.node[s.top + 1]);
		}
	}
	printf("\n");
}
void answer()  //输出答案
{
	for (int i = 0; i < cnt; i++)
		printf("%d ", ans[i]);
	printf("\n");
	
}
void show() //输出随机生成的无向图关系矩阵
{
	for (int i = 0; i < n; i++)
	{
		for (int j = 0; j < n; j++)
		{
			printf("%d\t", a[i][j]);
		}
		printf("\n");
	}
}


运行结果在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值