试图找到欧拉路径,但输出仅对半欧拉图正确。完全的欧拉图不正确

时间:2019-04-19 08:00:59

标签: c++ graph

大家好,星期五快乐。我正在完成这项工作,其中涉及实现图形数据结构以及邻接表和矩阵。它还要求确定是否可以一次绘制图形(我通过确定图形是欧拉还是半欧拉来完成此操作)。 我遇到的问题是,仅当图形为半欧拉(它具有2个奇数度的节点)时,我的打印路径的算法才有效。如果我在所有顶点均具有偶数度的图形中进行尝试,它将在图形中打印出一个不包含所有边的循环。该程序应采用命令行参数,该参数是包含用于构建图形的数据的文件的名称。

每个文件如下所示:

5 6
1 2
2 3
3 1
2 4
4 5
5 2

第一个数字是顶点数,第二个数字是边数。然后其余的线是边缘。例如,在上面的文件中,有5个顶点和6条边,并且在顶点1和2之间有一条边,依此类推。我的程序可以构建图形并将其正确打印出来,但是路径出现问题。

我已经实现了这样的类:

#include<vector>
#include<iostream>
#include<stack>
#include<list>
using namespace std;


class Graph{
    private:
        int num_vertices;
        int num_edges;
        vector<list<int> > adj_list;
        vector<vector<int> > adj_matrix;
    public:
        void insertVertex_adjList(int to_insert);
        void insertVertex(int to_insert);
        void insertVertex_adjMatrix(int to_insert);
        void insertEdge(int x,int y);
        void insertEdge_adjList(int x, int y);
        void insertEdge_adjMatrix(int x, int y);
        void removeEdge(int x, int y);
        void removeEdge_adjList(int x, int y);
        void removeEdge_adjMatrix(int x, int y);
        Graph():num_vertices(0),num_edges(0){
            adj_matrix.push_back(vector<int>(1,0));
        };
        void print_AdjList();
        void print_AdjMatrix();
        int getNumEdges(){return num_edges;}
        int getNumVertices(){return num_vertices;}
        bool has_eularian_path();
        bool has_eularian_circuit();
        void find_eularian_path();
        bool eulerian_path_helper(Graph &G, int u, stack<int> &s);
        int number_of_adjacent(list<int> A){return A.size()-1;}
        bool is_bridge(int x, int y);


};

Graph TesterHelper(int argc, char *argv[]);

这就是我寻找路径所涉及的函数的样子:

bool Graph::eulerian_path_helper(Graph &G, int u, stack<int> &s){
    s.push(u);
    if(adj_list[u-1].size()-1 == 0) return true;
    else{
        for(list<int>::iterator i = ++adj_list[u-1].begin(); i != adj_list[u-1].end();i++){

            G.removeEdge(u,*i);
            if(G.eulerian_path_helper(G,*i,s) == true) return true;
            else{
                G.insertEdge(u,*i);
            }
        }
        s.pop();
        return false;
    }
}

void Graph::find_eularian_path(){
    Graph G = *this; //to not mess with original graph.
    stack<int> s;
    int current = *adj_list[0].begin();
    if(G.has_eularian_circuit() == true) current = *adj_list[0].begin();
    else if(G.has_eularian_circuit()== false && G.has_eularian_path()==true){
        int current_size = adj_list[current].size() - 1;
        int odds = 0;
        for(int i =0; odds < 1; i++){
            current_size = adj_list[i].size()-1;
            if(current_size % 2 != 0) odds++;
            current = *adj_list[i].begin();
        }
    }
    else{ 
        cout << "Graph has no Euliarian Path";
        return;
    }

    eulerian_path_helper(G,current,s);
    while (!s.empty())
    {
     cout << ' ' << s.top();
     s.pop();
    }
    cout << endl;
    return;
}

Graph TesterHelper(int argc, char *argv[]){
    Graph to_return;
    fstream file;
    switch(argc){
      case 1: 
         cout << "No file specified.";
         return to_return;
      case 2: 
         file.open(argv[1]);
         if(file.is_open()==false){
             cout << "Invalid file name or error opening.";
             return to_return;
         }
         break;
   }
   int n, m, a;
   file >> n;
   file >> m;
   for(int i = 0; i < m;i++){
       file >> n;
       file >> a;
       to_return.insertEdge(n,a);
   }
   to_return.print_AdjList();
   cout << endl;
   to_return.print_AdjMatrix();
   cout << endl;
   if(to_return.has_eularian_circuit() == true){ 
       cout << "Graph is Eularian and can be drawn in one stroke starting from any vertex.";
   }
   else if(to_return.has_eularian_circuit() == false && to_return.has_eularian_path() == true ){
      cout << "Graph is semi-Eularian and can be drawn in one stroke starting at any of the 2 vertices with odd degree.";
   }
   if(to_return.has_eularian_circuit() == false && to_return.has_eularian_path() == false){
       cout << "Graph can not be drawn in a single stroke.";
   }


   return to_return;


}

最后main看起来像这样:

#include<iostream>
#include"Graph_Adjacency_List.h"
using namespace std;

int main(int argc, char *argv[]){
   Graph test = TesterHelper(argc,argv);
   test.find_eularian_path();
}

如果我运行的程序带有一个构建带有2个奇数度顶点的图形的文件,则一切正常。

例如,此文件:

5 7
1 2
2 3
3 1
2 4
4 5
5 2
5 3

我得到以下正确的输出:

:: ./a.out graph1.data
1->2->3
2->1->3->4->5
3->2->1->5
4->2->5
5->4->2->3

0 0 0 0 0 0
0 0 1 1 0 0
0 1 0 1 1 1
0 1 1 0 0 1
0 0 1 0 0 1
0 0 1 1 1 0

Graph is semi-Eularian and can be drawn in one stroke starting at any of the 2 vertices with odd degree.
 5 2 4 5 3 1 2 3

但是使用所有顶点都为偶数的文件运行该文件将失败。

5 6
1 2
1 3
2 3
2 4
2 5
4 5

这样打印不完整的路径:

:: ./a.out graph2.data
1->2->3
2->1->3->4->5
3->1->2
4->2->5
5->2->4

0 0 0 0 0 0
0 0 1 1 0 0
0 1 0 1 1 1
0 1 1 0 0 0
0 0 1 0 0 1
0 0 1 0 1 0

Graph is Eularian and can be drawn in one stroke starting from any vertex.
 1 3 2 1

对于冗长的帖子,我感到抱歉,但是我认为,如果其中不包含上面所有的信息,那将不是一个完整的例子。如果有人能提供解决方法的见解,我将不胜感激。预先谢谢你!

0 个答案:

没有答案