ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

第九章第十三节(无向图求欧拉回路)

2021-04-24 10:05:41  阅读:198  来源: 互联网

标签:第十三 int vertex next 无向 回路 顶点 图求 欧拉


欧拉环游:在图中找到一条路径,从起点开始,依此经过图中的所有边,一个边只能走一次,到达终点,终点和起点可以不同

欧拉回路:在图中找到一条路径,从起点开始,依此经过图中的所有边,最后回到起点,一个边只能走一次。

欧拉环游存在的条件:当前图是连通的,图中的恰有零个或两个顶点的度是奇数,其余顶点的度数为偶数,才会存在

欧拉回路存在的条件:当前图是连通的,图中所有的顶点的度是偶数时,欧拉回路必存在。

寻找欧拉回路的算法:如果从起点出发的所有边均已用完,那么图中就会有的部分遍历不到。最容易补救的方法就是找出有尚未访问的边的路径上的第一个顶点,并执行另外一次深度优先搜索。这将给出另外一个回路,把它拼接到原来的回路上。
继续该过程直到所有的边都被遍历到为止。

用到的数据结构

typedef struct Node* ptrNode;
struct Node {
	int v;				//记录顶点		
	ptrNode next;		
};
//用链表来存储欧拉回路走过的路径,head为链表的头节点
ptrNode head = (ptrNode)malloc(sizeof(struct Node));
ptrNode H = head;

//首先判断图是否为连通的,然后判断图中顶点的度是否都为偶数
int Viseted[MAXVERTEX];			//用一次dfs,记录图是否连通
int degree[MAXVERTEX];			//记录每个顶点的度
int ne;							//ne记录走过的边
Graph P;						//邻接矩阵存储图

主函数步骤

int main() {
	P = BuildGraph();			//初始化图
	if (IsConnect()) {			//IsConnect 函数判断图是否连通
		if (Isdegree()) {		//Isdegree 函数判断每个顶点的度是否为偶数
			printf("存在欧拉回路\n");
			isDfs(0);			//如果存在欧拉回路,从顶点0开始寻找欧拉回路
		}
		else {
			printf("图中节点的度数不为偶数,欧拉回路不存在\n");
		}
	}
	else {
		printf("该图不连通,无欧拉回路\n");
	}
	return 0;
}

判断图是否连通函数

void dfs(int vertex) {		//对图进行一次dfs,判断图是否连通
	Viseted[vertex] = 1;
	for (int i = 0; i < P->Nv; i++) {
		if (P->Graph[vertex][i] != 0 && Viseted[i] == 0) {
			dfs(i);
		}
	}
}
bool IsConnect() {
	dfs(0);				//进行一次dfs,然后判断,每个顶点是否都已访问到	
	for (int i = 0; i < P->Nv; i++) {
		if (Viseted[i] == 0)		
			return false;
	}
	return true;
}

判断图中顶点度的个数是否为偶数

bool Isdegree() {
	//判断图中各个顶点的度是否为偶数
	for (int i = 0; i < P->Nv; i++) {
		for (int j = 0; j < P->Nv; j++) {
			if (P->Graph[i][j] != 0) {
				//i到j有一条边。
				degree[j]++;
			}
		}
	}
	for (int i = 0; i < P->Nv;i++) {
		if (degree[i] % 2 != 0) {
			return false;
		}
	}
	return true;
}

求欧拉回路函数

void Dfs(int vertex) {
	//将走过的顶点,加入链表
	ptrNode p = (ptrNode)malloc(sizeof(struct Node));
	p->v = vertex;
	p->next = NULL;
	H->next = p;
	H = p;
	for (int i = 0; i < P->Nv; i++) {
		if (P->Graph[vertex][i] != 0) {
			P->Graph[vertex][i] = 0;	//将边删除
			P->Graph[i][vertex] = 0;	//将边删除
			ne += 2;					//统计当前走过的边数
			Dfs(i);						
			break;						//每个顶点不能往后再走
		}
	}
}
void euler(int vertex) {
	//求欧拉回路路径
	Dfs(vertex);
	int flag;
	ptrNode p,tmp,f=NULL;
	while (ne < P->Ne * 2) {
		for (p = head->next; p; p = p->next) {
			//找出从路径开始的第一个尚未走过边的顶点
			flag = 0;
			for (int i = 0; i < P->Nv; i++) {
				if (P->Graph[p->v][i] != 0) {
					//顶点p->v有边尚未走过
					f = H;			//记录当前链表尾的位置	
					flag = 1;		//找到尚未走过的边的顶点
					Dfs(p->v);		//p->v进行一次dfs
					break;
				}
			}
			if (flag == 1)
				break;
		}
		//此时f->next为从p->v顶点开始走过的路径
		//p为链表中要拼接的位置
		tmp = f;
		f = f->next->next;
		//将f拼接到p后面
		tmp->next = NULL;		//将链表尾置位空
		H = tmp;				//H为新拼接后的链表尾
		tmp = p->next;			//保存p->next
		p->next = f;		
		while (p->next)
			p = p->next;
		p->next = tmp;			//将tmp接回p->next
	}
	//输出欧拉回路
	for (p = head->next; p;p = p->next) {
		printf("%d ", p->v);
	}
}

标签:第十三,int,vertex,next,无向,回路,顶点,图求,欧拉
来源: https://blog.csdn.net/weixin_40540957/article/details/116082021

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有