Ваша самая большая проблема связана с вашей приоритетной очередью, которую вы реализуете как простой связанный список.Вы, похоже, не понимаете, когда и как использовать указатель на указатель узла.
Например, эта функция:
int isEmpty(Node **head) ...
проверяет только список.Он не изменяет его, поэтому достаточно передать указатель узла:
int isEmpty(Node *head) ...
Эта функция также не изменяет содержимое узлов, поэтому это можно сделать явным:
int isEmpty(const Node *head) ...
С другой стороны, функции push
, pop
и updateprt
должны иметь возможность изменять заголовок с помощью указателя, поэтому им требуется указатель на указатель узла.Ваша pop
функция, которая всегда меняет голову, делает это.Другие функции выглядят так:
void push(Node** head, int d, int p)
{
Node* start = (*head);
// ... do stuff with start, leave head alone ...
}
Здесь вы только что использовали указатель на указатель узла как чрезмерно неясный способ передачи информации о голове, но вы никогда не изменяете ее (за исключением специальногослучай вставки в пустой список).
Вот как должна выглядеть эта функция push
:
void push(Node **head, int d, int p)
{
Node *temp = newNode(d, p);
while (*head && (*head)->priority < p) {
head = &(*head)->next;
}
temp->next = *head;
*head = temp;
}
Обратите внимание, что особых случаев нет.Когда вы вызываете push(&queue, ...)
, вы передаете адрес указателя заголовка и можете изменить локальную переменную queue
в вызывающей функции, присвоив *head
.Когда вы просматриваете список с помощью head = &(*head)->next
, head
содержит адрес поля next
предыдущего узла, который вы также можете изменить с помощью *head
.Указатель на указатель добавляет один уровень косвенности и сообщает вам, откуда вы пришли, и позволяет вам изменить это значение.
В том же духе вы можете изменить (и упростить) свою функцию updateptr
:
void updateprt(Node** head, int data)
{
while (*head && (*head)->data != data) {
head = &(*head)->next;
}
if (*head) pop(head);
}
С этими изменениями ваша программа должна работать, но есть и другие вещи, на которые следует обратить внимание:
if (weight [src] [dest]! = 0 || weight [dest] [src]! = 0 && w
Условие (w1 == 0 || w2 == 0 && w < w1)
анализируется как (w1 == 0 || (w2 == 0 && w < w1))
, что, вероятно, не то, что вам нужно.Проверка на ноль не выполнена правильно, потому что вы никогда не инициализируете weight
.(Вы можете использовать calloc
вместо malloc
для создания массива с нулевой инициализацией.) `
Но зачем вообще иметь отдельный массив весов?Вы можете хранить вес для каждого ребра:
struct adjlistnode {
int data; // destination vertex
int weight;
struct adjlistnode* next;
};
То же самое относится и к массивам:
int Distance[100000], path[50];
Оба массива предоставляют одну запись для каждой вершины.Первый слишком щедрый («Я выделю немного больше, на всякий случай ...»), второй может быть слишком маленьким.(Вам не нужен путь для задачи, но всегда приятно иметь возможность проверить его. Переменная не является путем, однако она содержит следующий шаг к начальной точке для каждой вершины.)
Правила конкуренции гласят, что существует не более 3000 узлов, поэтому вы можете просто измерить массивы с помощью [3000]
, но вы также можете сделать их частью структуры графа и распределить их в соответствии с количеством вершин.
Удачи!