質問

The issue is I need to create a random undirected graph to test the benchmark of Dijkstra's algorithm using an array and heap to store vertices. AFAIK a heap implementation shall be faster than an array when running on sparse and average graphs, however when it comes to dense graphs, the heap should became less efficient than an array.

I tried to write code that will produce a graph based on the input - number of vertices and total number of edges (maximum number of edges in undirected graph is n(n-1)/2).

On the entrance I divide the total number of edges by the number of vertices so that I have a const number of edges coming out from every single vertex. The graph is represented by an adjacency list. Here is what I came up with:

#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#include <list>
#include <set>

#define MAX 1000
#define MIN 1

class Vertex
{
public:
    int Number;
    int Distance;
    Vertex(void);
    Vertex(int, int);
    ~Vertex(void);
};

Vertex::Vertex(void)
{
    Number = 0;
    Distance = 0;
}

Vertex::Vertex(int C, int D)
{
    Number = C;
    Distance = D;
}

Vertex::~Vertex(void)
{
}


int main()
{
    int VertexNumber, EdgeNumber;

    while(scanf("%d %d", &VertexNumber, &EdgeNumber) > 0)
    {
        int EdgesFromVertex = (EdgeNumber/VertexNumber);

        std::list<Vertex>* Graph = new std::list<Vertex> [VertexNumber];

        srand(time(NULL));

        int Distance, Neighbour;
        bool Exist, First;

        std::set<std::pair<int, int>> Added;

        for(int i = 0; i < VertexNumber; i++)
        {
            for(int j = 0; j < EdgesFromVertex; j++)
            {
                First = true;
                Exist = true;

                while(First || Exist)
                {
                    Neighbour = rand() % (VertexNumber - 1) + 0;

                    if(!Added.count(std::pair<int, int>(i, Neighbour)))
                    {
                        Added.insert(std::pair<int, int>(i, Neighbour));
                        Exist = false;
                    }
                    First = false;
                }
            }

            First = true;
            std::set<std::pair<int, int>>::iterator next = Added.begin();

            for(std::set<std::pair<int, int>>::iterator it = Added.begin(); it != Added.end();)
            {
                if(!First)
                    Added.erase(next);

                Distance = rand() % MAX + MIN;

                Graph[it->first].push_back(Vertex(it->second, Distance));
                Graph[it->second].push_back(Vertex(it->first, Distance));

                std::set<std::pair<int, int>>::iterator next = it;
                First = false;
            }
        }

        // Dijkstra's implementation
    }

    return 0;
}

I get an error:

set iterator not dereferencable" when trying to create graph from set data.

I know it has something to do with erasing set elements on the fly, however I need to erase them asap to diminish memory usage.

Maybe there's a better way to create some undirectioned graph? Mine is pretty raw, but that's the best I came up with. I was thinking about making a directed graph which is easier task, but it doesn't ensure that every two vertices will be connected.

I would be grateful for any tips and solutions!

役に立ちましたか?

解決

Piotry had basically the same idea I did, but he left off a step.

Only read half the matrix, and ignore you diagonal for writing values to. If you always want a node to have an edge to itself, add a one at the diagonal. If you always do not want a node to have an edge to itself, leave it as a zero.

You can read the other half of your matrix for a second graph for testing your implementation.

他のヒント

Look at the description of std::set::erase :

Iterator validity

  • Iterators, pointers and references referring to elements removed by the function are invalidated.
  • All other iterators, pointers and references keep their validity.

In your code, if next is equal to it, and you erase element of std::set by next, you can't use it. In this case you must (at least) change it and only after this keep using of it.

ライセンス: CC-BY-SA帰属
所属していません StackOverflow
scroll top