Dijkstra算法中的Segmentation Core Dump问题
Segmentation Core Dump Problem in Dijkstra Algorithm
我尝试用邻接表实现 Dijkstra 算法,当我从 updatePriority() 函数中删除 cout 语句时,代码表现出奇怪的行为,它抛出分段核心转储错误,如果包含 cout 语句,它不会抛出任何错误,一切正常。
可能是什么原因造成的?
我在下面包含了我的代码
谢谢..
#include <iostream>
using namespace std;
struct Node
{
int vertex;
int edgeCost;
struct Node *next;
};
struct Graph
{
int numVertices;
int *visited;
int *distance;
int *path;
struct Node **adjLists;
};
struct PQueue
{
int item;
int priority;
struct PQueue *next;
};
Node *createNode(int v)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->vertex = v;
node->edgeCost = 0;
node->next = NULL;
return node;
}
Graph *createGraph(int vertices)
{
struct Graph *graph = (struct Graph *)malloc(sizeof(struct Graph));
graph->numVertices = vertices;
graph->adjLists = (struct Node **)malloc(vertices * sizeof(struct node *));
graph->visited = (int *)malloc(vertices * sizeof(int));
graph->distance = (int *)malloc(vertices * sizeof(int));
graph->path = (int *)malloc(vertices * sizeof(int));
for (int i = 0; i < vertices; i++)
{
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}
void addEdge(struct Graph *graph, int src, int dest, int cost)
{
struct Node *newNode = createNode(dest);
newNode->edgeCost = cost;
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;
newNode = createNode(src);
newNode->edgeCost = cost;
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}
void printGraph(struct Graph *graph)
{
int v;
for (v = 0; v < graph->numVertices; v++)
{
struct Node *temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp)
{
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}
}
PQueue *createQueueNode(int item, int priority)
{
struct PQueue *node = (struct PQueue *)malloc(sizeof(struct PQueue));
node->item = item;
node->priority = priority;
node->next = NULL;
return node;
}
void enqueue(struct PQueue **head, int item, int priority)
{
struct PQueue *node = createQueueNode(item, priority);
if (*head == NULL)
{
*head = node;
}
else
{
struct PQueue *temp = *head;
if (priority <= temp->priority)
{
node->next = temp;
*head = node;
}
else
{
struct PQueue *t;
while (temp != NULL && priority < temp->priority)
{
t = temp;
temp = temp->next;
}
t->next = node;
node->next = temp;
}
}
}
PQueue *dequeue(struct PQueue **head)
{
if (*head == NULL)
{
cout << "queue is empty";
return NULL;
}
struct PQueue *temp = *head;
*head = (*head)->next;
return temp;
}
void printQueue(struct PQueue *head)
{
struct PQueue *temp = head;
while (temp != NULL)
{
cout << "item " << temp->item << " priority " << temp->priority << endl;
temp = temp->next;
}
cout << "----------------------" << endl;
}
void updatePriority(struct PQueue **head, int item, int priority)
{
struct PQueue *temp = *head;
while (temp != NULL && temp->item != item)
{
// cout << temp->item;
temp = temp->next;
}
if (temp == NULL)
{
enqueue(&(*head), item, priority);
}
else
{
temp->priority = priority;
}
}
void Dijkstra(struct Graph *graph, int src)
{
struct PQueue *head = createQueueNode(src, 0);
int v, cost;
for (int i = 0; i < graph->numVertices; i++)
{
graph->distance[i] = -1;
}
graph->distance[src] = 0;
while (head != NULL)
{
v = dequeue(&head)->item;
struct Node *temp = graph->adjLists[v];
while (temp != NULL)
{
int newDistance = graph->distance[v] + temp->edgeCost;
if (graph->distance[temp->vertex] == -1)
{
graph->distance[temp->vertex] = newDistance;
updatePriority(&head, temp->vertex, newDistance);
}
else if (graph->distance[temp->vertex] > newDistance)
{
graph->distance[temp->vertex] = newDistance;
updatePriority(&head, temp->vertex, newDistance);
}
temp = temp->next;
}
}
}
int main()
{
struct Graph *graph = createGraph(7);
addEdge(graph, 0, 2, 1);
addEdge(graph, 0, 3, 2);
addEdge(graph, 1, 2, 2);
addEdge(graph, 2, 3, 1);
addEdge(graph, 1, 5, 3);
addEdge(graph, 2, 4, 3);
addEdge(graph, 4, 5, 2);
addEdge(graph, 3, 6, 1);
addEdge(graph, 6, 5, 1);
// printGraph(graph);
Dijkstra(graph, 2);
cout << endl;
for (int i = 0; i < graph->numVertices; i++)
{
cout << "distance to " << i << " is " << graph->distance[i] << endl;
}
return 0;
}
enqueue
这一行有错误:
while (temp != NULL && priority < temp->priority)
此条件在验证第一次评估时将为假,因为前面的 if
条件为假。因此,变量 t
将保持未初始化状态,并且以下行将执行不受控制的取消引用,可能会引发分段错误:
t->next = node;
在某处添加一个 cout
可能会让人感到困惑,这可能会决定是否发生分段错误......这完全取决于 t
中的实际(未定义)值是什么编译代码。
修正当然是改变while
条件:
while (temp != NULL && priority > temp->priority)
我尝试用邻接表实现 Dijkstra 算法,当我从 updatePriority() 函数中删除 cout 语句时,代码表现出奇怪的行为,它抛出分段核心转储错误,如果包含 cout 语句,它不会抛出任何错误,一切正常。
可能是什么原因造成的?
我在下面包含了我的代码 谢谢..
#include <iostream>
using namespace std;
struct Node
{
int vertex;
int edgeCost;
struct Node *next;
};
struct Graph
{
int numVertices;
int *visited;
int *distance;
int *path;
struct Node **adjLists;
};
struct PQueue
{
int item;
int priority;
struct PQueue *next;
};
Node *createNode(int v)
{
struct Node *node = (struct Node *)malloc(sizeof(struct Node));
node->vertex = v;
node->edgeCost = 0;
node->next = NULL;
return node;
}
Graph *createGraph(int vertices)
{
struct Graph *graph = (struct Graph *)malloc(sizeof(struct Graph));
graph->numVertices = vertices;
graph->adjLists = (struct Node **)malloc(vertices * sizeof(struct node *));
graph->visited = (int *)malloc(vertices * sizeof(int));
graph->distance = (int *)malloc(vertices * sizeof(int));
graph->path = (int *)malloc(vertices * sizeof(int));
for (int i = 0; i < vertices; i++)
{
graph->adjLists[i] = NULL;
graph->visited[i] = 0;
}
return graph;
}
void addEdge(struct Graph *graph, int src, int dest, int cost)
{
struct Node *newNode = createNode(dest);
newNode->edgeCost = cost;
newNode->next = graph->adjLists[src];
graph->adjLists[src] = newNode;
newNode = createNode(src);
newNode->edgeCost = cost;
newNode->next = graph->adjLists[dest];
graph->adjLists[dest] = newNode;
}
void printGraph(struct Graph *graph)
{
int v;
for (v = 0; v < graph->numVertices; v++)
{
struct Node *temp = graph->adjLists[v];
printf("\n Adjacency list of vertex %d\n ", v);
while (temp)
{
printf("%d -> ", temp->vertex);
temp = temp->next;
}
printf("\n");
}
}
PQueue *createQueueNode(int item, int priority)
{
struct PQueue *node = (struct PQueue *)malloc(sizeof(struct PQueue));
node->item = item;
node->priority = priority;
node->next = NULL;
return node;
}
void enqueue(struct PQueue **head, int item, int priority)
{
struct PQueue *node = createQueueNode(item, priority);
if (*head == NULL)
{
*head = node;
}
else
{
struct PQueue *temp = *head;
if (priority <= temp->priority)
{
node->next = temp;
*head = node;
}
else
{
struct PQueue *t;
while (temp != NULL && priority < temp->priority)
{
t = temp;
temp = temp->next;
}
t->next = node;
node->next = temp;
}
}
}
PQueue *dequeue(struct PQueue **head)
{
if (*head == NULL)
{
cout << "queue is empty";
return NULL;
}
struct PQueue *temp = *head;
*head = (*head)->next;
return temp;
}
void printQueue(struct PQueue *head)
{
struct PQueue *temp = head;
while (temp != NULL)
{
cout << "item " << temp->item << " priority " << temp->priority << endl;
temp = temp->next;
}
cout << "----------------------" << endl;
}
void updatePriority(struct PQueue **head, int item, int priority)
{
struct PQueue *temp = *head;
while (temp != NULL && temp->item != item)
{
// cout << temp->item;
temp = temp->next;
}
if (temp == NULL)
{
enqueue(&(*head), item, priority);
}
else
{
temp->priority = priority;
}
}
void Dijkstra(struct Graph *graph, int src)
{
struct PQueue *head = createQueueNode(src, 0);
int v, cost;
for (int i = 0; i < graph->numVertices; i++)
{
graph->distance[i] = -1;
}
graph->distance[src] = 0;
while (head != NULL)
{
v = dequeue(&head)->item;
struct Node *temp = graph->adjLists[v];
while (temp != NULL)
{
int newDistance = graph->distance[v] + temp->edgeCost;
if (graph->distance[temp->vertex] == -1)
{
graph->distance[temp->vertex] = newDistance;
updatePriority(&head, temp->vertex, newDistance);
}
else if (graph->distance[temp->vertex] > newDistance)
{
graph->distance[temp->vertex] = newDistance;
updatePriority(&head, temp->vertex, newDistance);
}
temp = temp->next;
}
}
}
int main()
{
struct Graph *graph = createGraph(7);
addEdge(graph, 0, 2, 1);
addEdge(graph, 0, 3, 2);
addEdge(graph, 1, 2, 2);
addEdge(graph, 2, 3, 1);
addEdge(graph, 1, 5, 3);
addEdge(graph, 2, 4, 3);
addEdge(graph, 4, 5, 2);
addEdge(graph, 3, 6, 1);
addEdge(graph, 6, 5, 1);
// printGraph(graph);
Dijkstra(graph, 2);
cout << endl;
for (int i = 0; i < graph->numVertices; i++)
{
cout << "distance to " << i << " is " << graph->distance[i] << endl;
}
return 0;
}
enqueue
这一行有错误:
while (temp != NULL && priority < temp->priority)
此条件在验证第一次评估时将为假,因为前面的 if
条件为假。因此,变量 t
将保持未初始化状态,并且以下行将执行不受控制的取消引用,可能会引发分段错误:
t->next = node;
在某处添加一个 cout
可能会让人感到困惑,这可能会决定是否发生分段错误......这完全取决于 t
中的实际(未定义)值是什么编译代码。
修正当然是改变while
条件:
while (temp != NULL && priority > temp->priority)