std::bad_alloc 在大数据集的 dijkstra 计算期间
std::bad_alloc during dijkstra calculation for big dataset
我正在尝试使用 dijkstra 算法求解大图的最短路径。
问题是当我在 CLion 中执行程序时,我总是在节点 491 获得 std::bad alloc,但是当我尝试在我的 Ubuntu VM 上执行相同操作时,我在开始时得到核心转储。
我是 c++ 的新手,所以我很难理解为什么会这样。
这是我的代码:
实用工具:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <ctime>
#define INFINITY 9999999
int maxNode = 0;
using namespace std;
vector<int> loadFile(const string &path) {
vector<int> graph;
ifstream file;
file.open(path);
if (!file.fail()) {
string line;
while (getline(file, line)) {
stringstream ss(line);
for (int i; ss >> i;) {
if (i + 1 > maxNode)
maxNode = i + 1;
graph.push_back(i);
if (ss.peek() == ';')
ss.ignore();
}
}
file.close();
}
return graph;
}
int **formatGraph(vector<int> inData) {
int **graph = 0;
int currentIndex = 0;
int srcNode = inData[0];
int dstNode = inData[1];
int cost = inData[2];
graph = new int *[maxNode];
for (int i = 0; i < maxNode; i++) {
graph[i] = new int[maxNode];
for (int j = 0; j < maxNode; j++) {
if (srcNode == i && dstNode == j) {
graph[i][j] = cost;
currentIndex++;
srcNode = inData[currentIndex * 3];
dstNode = inData[currentIndex * 3 + 1];
cost = inData[currentIndex * 3 + 2];
//printf("%d %d\n", i, j);
} else
graph[i][j] = 0;
}
}
for (int i = 0; i < maxNode; i++) {
for (int j = 0; j < maxNode; j++) {
graph[j][i] = graph[i][j];
}
}
return graph;
}
算法:
void dijkstra(int **G, int n, int startnode) {
printf("%d\n", startnode);
int **cost = new int *[maxNode];
int distance[maxNode], pred[maxNode];
int visited[maxNode], count, mindistance, nextnode, i, j;
for (i = 0; i < n; i++) {
cost[i] = new int[maxNode];
for (j = 0; j < n; j++)
cost[i][j] = 0;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (G[i][j] == 0)
cost[i][j] = INFINITY;
else
cost[i][j] = G[i][j];
for (i = 0; i < n; i++) {
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
count = 1;
while (count < n - 1) {
mindistance = INFINITY;
for (i = 0; i < n; i++) {
if (distance[i] < mindistance && !visited[i]) {
mindistance = distance[i];
nextnode = i;
}
}
visited[nextnode] = 1;
for (i = 0; i < n; i++) {
if (!visited[i]) {
if (mindistance + cost[nextnode][i] < distance[i]) {
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
}
}
count++;
}
delete[] cost;
for (i = 0; i < n; i++)
if (i != startnode) {
j = i;
do {
j = pred[j];
} while (j != startnode);
}
}
这是我的主要功能:
int main() {
vector<int> graph = loadFile("..\data\newFile2.csv");
int **graphConverted = formatGraph(graph);
//printMatrix(graphConverted);
clock_t begin = clock();
for (int i = 0; i < maxNode; i++)
dijkstra(graphConverted, maxNode, i);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("\nTime: %f", elapsed_secs);
return 0;
}
首先将数据加载到向量中,然后将其转换为邻接矩阵。
数据以以下形式存储:
src_node;dst_node;成本
1;2;3
1;3;30
1;66;20
等等
数据集包含 1004 个节点和 25571 条边。
你能给我建议解决这个问题的方法吗?
在 dijkstra
中,您在这里有动态内存分配:
int **cost = new int *[maxNode];
这里循环遍历 i
:
cost[i] = new int[maxNode];
您在此函数中只有一次调用 delete[]
:
delete[] cost;
因此,第二行 new
中的所有分配都保证会泄漏。一段时间后你会内存不足,导致 std::bad_alloc
.
您需要将每个 new[]
调用与 恰好一个 delete[]
调用匹配。
根本不要使用 new
/delete
。而是将所有数组声明为 std::vector
,这将自动处理。
也不要使用变长数组,例如
int distance[maxNode], pred[maxNode];
它们是非标准的编译器扩展。也制作这些 std::vector
。
我正在尝试使用 dijkstra 算法求解大图的最短路径。 问题是当我在 CLion 中执行程序时,我总是在节点 491 获得 std::bad alloc,但是当我尝试在我的 Ubuntu VM 上执行相同操作时,我在开始时得到核心转储。
我是 c++ 的新手,所以我很难理解为什么会这样。
这是我的代码:
实用工具:
#include <iostream>
#include <fstream>
#include <string>
#include <vector>
#include <sstream>
#include <ctime>
#define INFINITY 9999999
int maxNode = 0;
using namespace std;
vector<int> loadFile(const string &path) {
vector<int> graph;
ifstream file;
file.open(path);
if (!file.fail()) {
string line;
while (getline(file, line)) {
stringstream ss(line);
for (int i; ss >> i;) {
if (i + 1 > maxNode)
maxNode = i + 1;
graph.push_back(i);
if (ss.peek() == ';')
ss.ignore();
}
}
file.close();
}
return graph;
}
int **formatGraph(vector<int> inData) {
int **graph = 0;
int currentIndex = 0;
int srcNode = inData[0];
int dstNode = inData[1];
int cost = inData[2];
graph = new int *[maxNode];
for (int i = 0; i < maxNode; i++) {
graph[i] = new int[maxNode];
for (int j = 0; j < maxNode; j++) {
if (srcNode == i && dstNode == j) {
graph[i][j] = cost;
currentIndex++;
srcNode = inData[currentIndex * 3];
dstNode = inData[currentIndex * 3 + 1];
cost = inData[currentIndex * 3 + 2];
//printf("%d %d\n", i, j);
} else
graph[i][j] = 0;
}
}
for (int i = 0; i < maxNode; i++) {
for (int j = 0; j < maxNode; j++) {
graph[j][i] = graph[i][j];
}
}
return graph;
}
算法:
void dijkstra(int **G, int n, int startnode) {
printf("%d\n", startnode);
int **cost = new int *[maxNode];
int distance[maxNode], pred[maxNode];
int visited[maxNode], count, mindistance, nextnode, i, j;
for (i = 0; i < n; i++) {
cost[i] = new int[maxNode];
for (j = 0; j < n; j++)
cost[i][j] = 0;
}
for (i = 0; i < n; i++)
for (j = 0; j < n; j++)
if (G[i][j] == 0)
cost[i][j] = INFINITY;
else
cost[i][j] = G[i][j];
for (i = 0; i < n; i++) {
distance[i] = cost[startnode][i];
pred[i] = startnode;
visited[i] = 0;
}
distance[startnode] = 0;
visited[startnode] = 1;
count = 1;
while (count < n - 1) {
mindistance = INFINITY;
for (i = 0; i < n; i++) {
if (distance[i] < mindistance && !visited[i]) {
mindistance = distance[i];
nextnode = i;
}
}
visited[nextnode] = 1;
for (i = 0; i < n; i++) {
if (!visited[i]) {
if (mindistance + cost[nextnode][i] < distance[i]) {
distance[i] = mindistance + cost[nextnode][i];
pred[i] = nextnode;
}
}
}
count++;
}
delete[] cost;
for (i = 0; i < n; i++)
if (i != startnode) {
j = i;
do {
j = pred[j];
} while (j != startnode);
}
}
这是我的主要功能:
int main() {
vector<int> graph = loadFile("..\data\newFile2.csv");
int **graphConverted = formatGraph(graph);
//printMatrix(graphConverted);
clock_t begin = clock();
for (int i = 0; i < maxNode; i++)
dijkstra(graphConverted, maxNode, i);
clock_t end = clock();
double elapsed_secs = double(end - begin) / CLOCKS_PER_SEC;
printf("\nTime: %f", elapsed_secs);
return 0;
}
首先将数据加载到向量中,然后将其转换为邻接矩阵。 数据以以下形式存储:
src_node;dst_node;成本
1;2;3
1;3;30
1;66;20
等等
数据集包含 1004 个节点和 25571 条边。
你能给我建议解决这个问题的方法吗?
在 dijkstra
中,您在这里有动态内存分配:
int **cost = new int *[maxNode];
这里循环遍历 i
:
cost[i] = new int[maxNode];
您在此函数中只有一次调用 delete[]
:
delete[] cost;
因此,第二行 new
中的所有分配都保证会泄漏。一段时间后你会内存不足,导致 std::bad_alloc
.
您需要将每个 new[]
调用与 恰好一个 delete[]
调用匹配。
根本不要使用 new
/delete
。而是将所有数组声明为 std::vector
,这将自动处理。
也不要使用变长数组,例如
int distance[maxNode], pred[maxNode];
它们是非标准的编译器扩展。也制作这些 std::vector
。