Search code examples
c++classstdvectoradjacency-liststdlist

I need to remove duplicate vertices(adjacency list)


File test.txt

  • 6 (This is the number of vertices)

  • 1 4 (Еhe first is the number of the vertex, and the second is the number of the vertex to which the edge is being constructed.

  • 1 6

  • 2 1

  • 2 3

  • 2 4

  • 2 5

  • 3 2

  • 3 5

  • 4 1

  • 4 2

  • 4 5

  • 5 2

  • 5 3

  • 5 4

  • 6 1

    #include <iostream>
    #include <fstream>
    #include <vector>
    #include <list>
    
    using namespace std;
    
    class edge
    {
    private:
    int node2id, nodeid;
    public:
    edge(int id, int id2)
    {
        node2id = id2;
        nodeid = id;
    
    }
    
    int getnodeid()
    {
        return nodeid;
    }
    int getnodeid2()
    {
        return node2id;
    }
    
    };
    
    int main()
    { 
    int totalnode, node1, node2;
    ifstream input("test.txt");
    input >> totalnode;
    vector<list<edge>>adjList(totalnode);
    while (input >> node1 >> node2)
    {
        adjList[node1 - 1].push_back(edge(node2, node1));
    }
    
    int c = 1;
    vector<list<edge>>::iterator i;
    for (i = adjList.begin(); i != adjList.end(); i++)
    {
        cout << c << " -- ";
        list<edge>  li = *i;
        list<edge>::iterator iter;
        for (iter = li.begin(); iter != li.end(); iter++)
        {
            cout << "[" << (*iter).getnodeid() << "] ";
        }
        cout << endl;
        c++;
    }
    
    while (input >> node1 >> node2)
    {
        adjList[node1 - 1].push_back(edge(node1, node1));
    }
    
    cout << "\n";
    

And in this part, new vertices are created and I don't know how to remove the same ones.

vector<list<edge>>::iterator j;

for (j = adjList.begin(); j != adjList.end(); j++)
{


    //cout << c << " -- ";
    list<edge>  li = *j;
    list<edge>::iterator iter;
    for (iter = li.begin(); iter != li.end(); iter++)
    {

        cout << c <<" -- " << "[" << (*iter).getnodeid2() << "] " << "[" << (*iter).getnodeid() << "]\n";
        c++;

    }


}
return 0;
}

Output

Adjacency list will be created


1 -- [2] [4] [6]
2 -- [1] [3] [4] [5]
3 -- [2] [5]
4 -- [1] [2] [5]
5 -- [2] [3] [4]
6 -- [1]

These vertices were created, but for example, vertices 7 and 10 (and so on) have the same connections. And you need to make sure that there are no identical vertices.

7 -- [1] [2]
8 -- [1] [4]
9 -- [1] [6]
10 -- [2] [1]
11 -- [2] [3]
12 -- [2] [4]
13 -- [2] [5]
14 -- [3] [2]
15 -- [3] [5]
16 -- [4] [1]
17 -- [4] [2]
18 -- [4] [5]
19 -- [5] [2]
20 -- [5] [3]
21 -- [5] [4]
22 -- [6] [1]

 

Solution

  • Based on what you have so far, seems like you don't really need a edge class. All the information could be stored in int instead.


    And to solve what you wanted, you could first store all the edges in an std::vector<std::set<int> like:

    while (input >> node1 >> node2)
    {
        adjList[node1 - 1].insert(node2);
    }
    

    By using a set, all the edges are stored in numerical ascending order. So instead of:

    10 -- [2] [1]
    

    You would have:

    10 -- [1] [2]
    

    Now you can just parse the vector into an std::map, like:

    std::map<std::set<int>, int> tempMap;
    
    for(auto i = 0; i < totalnode; ++i)
    {
        s.try_emplace(adjList[i], i);
    }
    

    This would automatically get rid of node that already have another node with the same set of adjacent nodes (like you described in your question).

    However, I'm only calling this a tempMap because at the moment, they are ordered by their adjacencies, not their name.

    So what you could do is:

    std::map<int, std::set<int>> adjMap;
    
    for(auto& [key, value] : tempMap)
    {
        adjMap.emplace(value, key);
    }
    

    Now you can loop through the entire map like:

    for(auto& [node, edges] : adjMap
    {
        std::cout << node << " -- ";
        for(auto& edge: edges)
        {
            std::cout << "[" << edge << "]";
        }
        std::cout << "\n";
    }
    

    Side note, I notice you have written code like:

    vector<list<edge>>::iterator i;
    for (i = adjList.begin(); i != adjList.end(); i++) { // your loop }
    

    Instead, you could just use:

    for(auto it = adjList.begin(); it != adjList.end(); ++it) { // your loop }
        ^^^^
    

    It automatically assign i with the appropriate iterator type for that container.

    Or even in many case:

    for(auto& item : adjList) { // your loop }
    

    And you can use item in your loop the same way as *i from previous example.