并查集操作
文件UnionFindSet.h
#ifndef UNIONFINDSET_H_INCLUDED
#define UNIONFINDSET_H_INCLUDED
//并查集
//这存的是对顶点的直接领导
int pre[100];
//存的是各顶点的度
int degree[100];
//查找x的最高领导是谁并返回
int find(int x){
int t = x;
while(pre[t] != -1){
t = pre[t];
}
return t;
}
//合并,如果x和y的最高*不是同一个
//则将其中一个*的*设为另一个
void join(int x , int y){
int fx = find(x);
int fy = find(y);
if(fx != fy){
pre[fx] = fy;
}
}
//判断是否是连通图,如果最高*
//只有一个就是连通图即只有一个pre为-1
bool IsConnection(int vertex , int edge){
int num = 0;
for(int i = 1 ; i <= vertex ; i++){
if(pre[i] == -1){
num++;
}
}
if(num == 1){
return true;
}else{
return false;
}
}
#endif // UNIONFINDSET_H_INCLUDED
图结构
文件Graph.h
#ifndef GRAPH_H_INCLUDED
#define GRAPH_H_INCLUDED
#include <iostream>
#include <cstdlib>
#include "UnionFindSet.h"
#include <Queue>
using namespace std;
//链表节点结构
typedef struct ListNode {
int index;
struct ListNode *next;
}ListNode;
//数组顶点结构
typedef struct Vertex{
ListNode *firstvex;
char data;
}Vertex;
//邻接表结构
typedef struct Graph{
Vertex vertex[256];
int vexnum , edgenum;
}Graph;
void Init(Graph &G);
void Create_Graph(Graph &G);
void BFSTraverse(Graph G);
void Init(Graph &G){
G.edgenum = 0;
G.vexnum = 0;
}
//这个num是用来记录度为奇数顶点的个数
int num = 0;
void Create_Graph(Graph &G){
cout << "请输入顶点数:" ;
cin >> G.vexnum;
cout << "请输入边数:";
cin >> G.edgenum;
int i , j , k;
//初始化pre和degree分别为-1和0
for(i = 1 ; i <= G.vexnum ; i++){
pre[i] = -1;
degree[i] = 0;
}
//第0号位置不用,输入顶点
for (i = 1 ; i <= G.vexnum ; i++){
cout << "第" << i << "个顶点为:";
cin >> G.vertex[i].data;
G.vertex[i].firstvex = NULL;
}
//输入边
for(int k = 0 ; k < G.edgenum ; k++){
cout << "请输入边(vi , vj)的下标i,j:";
cin >> i >> j;
//进行并查集操作
int fx = find(i);
int fy = find(j);
if(fx != fy){
join(fx , fy);
}
//对应顶点度加一
degree[i]++;
degree[j]++;
//构造边即将顶点下标存入链结构中
//前插法,尾插法需要遍历好麻烦
ListNode *e = new ListNode;
e->index = j;
e->next = G.vertex[i].firstvex;
G.vertex[i].firstvex = e;
e = new ListNode;
e->index = i;
e->next = G.vertex[j].firstvex;
G.vertex[j].firstvex = e;
}
//记录度为奇数的点个数
for(int k = 1 ; k <= G.vexnum ; k++){
if(degree[k] % 2 == 1){
num++;
}
}
}
//是否访问的标志
int visited[256];
//广度遍历输出路径
//深度遍历输出的不是路径仅仅是打印顶点
void BFSTraverse(Graph G){
//C++的队列
queue<int> Q;
int i;
//初始化为未被访问
for(i = 1 ; i <= G.vexnum ; i++){
visited[i] = 0;
}
//遍历每节点还是为了防止非连图
//连通图只用循环一次
for(i = 1 ; i <= G.vexnum ; i++){
if(visited[i] == 0){
visited[i] = 1;
cout << G.vertex[i].data;
Q.push(i);
while(!Q.empty()){
//将队头元素出栈
int index = Q.front();
Q.pop();
//w指向队头元素相邻的第一个元素
ListNode *w = G.vertex[index].firstvex;
//然后一直将栈顶元素所有相邻顶点遍历完
//再到相邻顶点遍历
while(w){
if(visited[w->index] == 0){
visited[w->index] = 1;
cout << G.vertex[w->index].data;
//将相邻顶点入队,下一次遍历它
Q.push(w->index);
}
w = w->next;
}
}
}
}
}
#endif // GRAPH_H_INCLUDED
文件main.cpp
#include <iostream>
#include "Graph.h"
using namespace std;
int main()
{
Graph G;
Init(G);
Create_Graph(G);
//欧拉回路必须没有度为奇数的点
//欧拉路径有两个度为奇数的点
//都必须是连通图
if(IsConnection(G.vexnum , G.edgenum) && (num == 0 || num == 2 ) ){
if(num == 0){
cout << "有欧拉回路" << endl;
}
else if (num == 2){
cout << "有欧拉路径" << endl;
cout << "欧拉路径为:";
BFSTraverse(G);
}
}else {
cout << "无欧拉" << endl;
}
}