欧拉回路判断和路径输出,复制可用

并查集操作
文件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;
    }
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值