问题是我需要创建一个随机无向图来测试Dijkstra's algorithm的基准测试,使用数组和堆来存储顶点。在稀疏和平均图上运行时,AFAIK堆实现应该比数组更快,但是当涉及到密集图时,堆的效率应该低于数组。
我尝试编写将根据输入生成图形的代码 - 顶点数和边数总数(无向图中的最大边数为n(n-1)/ 2)。
在入口处,我将边的总数除以顶点的数量,这样我就有从每个顶点出来的const数量的边。该图由邻接列表表示。以下是我提出的建议:
#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;
}
我收到错误:
尝试从设置数据创建图时,设置迭代器不可解除引用。
我知道它与动态删除设置元素有关,但我需要尽可能地删除它们以减少内存使用。
也许有更好的方法来创建一些非定向图?我很生,但这是我想出的最好的。我正在考虑制作一个更容易完成任务的有向图,但它并不能确保每两个顶点都能连接起来。
我会很感激任何提示和解决方案!
答案 0 :(得分:0)
查看std::set::erase
的{{3}}:
迭代器有效期
在您的代码中,如果next
等于it
,并且您std::set
删除了next
的元素,则无法使用it
。在这种情况下,您必须(至少)更改it
并且仅在此之后继续使用it
。
答案 1 :(得分:0)
Piotry和我的想法基本相同,但他离开了一步。
只读取矩阵的一半,并忽略对角线写入值。如果您总是希望节点有自己的边缘,请在对角线上添加一个节点。如果您始终不希望节点有自己的边缘,请将其保留为零。
您可以阅读矩阵的另一半,以获取第二个图表来测试您的实现。