двойной указатель на узел - PullRequest
0 голосов
/ 16 ноября 2018

Мои сомнения касаются только указателя. Здесь head - двойной указатель на Queue, если мы используем *head, чем мы получаем доступ к местоположению (или адресу, переданному) внутри main, но когда мы используем просто head, чем мы используем заголовок только в текущей функции, которая будет удерживать адрес указателя на Queue теперь, когда мы делаем это head=&(*head)->next, поскольку поскольку (* head) -> next сам по себе является адресом, а когда мы используем & перед этим это, чем будет отдельный блок, будет создан блок памяти, который будет содержать адрес (* head) -> next, и мы назначаем этот адрес главе. У меня есть это сомнение, потому что это как двухэтапный процесс, который мы не можем напрямую поместить (* head) -> рядом с чем-то внутри head, нам нужно передать адрес адреса, для чего нам потребуется дополнительный блок, и когда цикл будет выполнено, скажем, n раз, чем будет n промежуточных блоков? Пожалуйста, скажите мне, если я прав или нет и скажи правильную логику спасибо

void queue_push(Queue **head, int d, int p)
{
    Queue *q = queue_new(d, p);

    while (*head && (*head)->priority < p) {
        head = &(*head)->next;
    }

    q->next = *head;
    *head = q;
}

Полная программа

    #include <stdio.h>
    #include <stdlib.h>
    #include <assert.h>

    typedef struct Queue Queue;

    struct Queue {
        int data;
        int priority;
        Queue *next;
    };

    Queue *queue_new(int d, int p)
    {
        Queue *n = malloc(sizeof(*n));

        n->data = d;
        n->priority = p;
        n->next = NULL;

        return n;
    }

    int queue_pop(Queue **head)
    {
        assert(*head);

        Queue *old = *head;
        int res = old->data;

        *head = (*head)->next;
        free(old);

        return res;
    }

    void queue_remove(Queue **head, int data)
    {
        while (*head && (*head)->data != data) {
            head = &(*head)->next;
        }

        if (*head) queue_pop(head);
    }

    void queue_push(Queue **head, int d, int p)
    {
        Queue *q = queue_new(d, p);

        while (*head && (*head)->priority < p) {
            head = &(*head)->next;
        }

        q->next = *head;
        *head = q;
    }


    int queue_empty(Queue *head)
    {
        return (head == NULL);
    }

    void queue_print(const Queue *q)
    {
        while (q) {
            printf("%d[%d] ", q->data, q->priority);
            q = q->next;
        }

        puts("$");
    }

    typedef struct Graph Graph;
    typedef struct Edge Edge;

    struct Edge {
        int vertex;
        int weight;
        Edge *next;
    };

    struct Graph {
        int v;
        Edge **edge;
        int *dist;
        int *path;
    };

    Graph *graph_new(int v)
    {
        Graph *G = malloc(sizeof(*G));

        G->v = v;
        G->edge = calloc(v, sizeof(*G->edge));
        G->dist = calloc(v, sizeof(*G->dist));
        G->path = calloc(v, sizeof(*G->path));

        return G;
    }

    void graph_delete(Graph *G)
    {
        if (G) {
            for (int i = 0; i < G->v; i++) {
                Edge *e = G->edge[i];

                while (e) {
                    Edge *old = e;

                    e = e->next;
                    free(old);
                }
            }

            free(G->edge);
            free(G->dist);
            free(G->path);
            free(G);
        }
    }

    Edge *edge_new(int vertex, int weight, Edge *next)
    {
        Edge *e = malloc(sizeof(*e));

        e->vertex = vertex;
        e->weight = weight;
        e->next = next;

        return e;
    }

    void graph_edge(Graph *G, int u, int v, int w)
    {
        G->edge[u] = edge_new(v, w, G->edge[u]);
        G->edge[v] = edge_new(u, w, G->edge[v]);
    }

    void dijkstra(const Graph *G, int s)
    {
        Queue *queue = NULL;

        for (int i = 0; i < G->v; i++) G->dist[i] = -1;
        G->dist[s] = 0;

        queue_push(&queue, s, 0);

        while (!queue_empty(queue)) {
            int v = queue_pop(&queue);
            Edge *e = G->edge[v];

            while (e) {
                int w = e->vertex;
                int d = G->dist[v] + e->weight;

                if (G->dist[w] == -1) {
                    G->dist[w] = d;
                    G->path[w] = v;

                    queue_push(&queue, w, d);
                }

                if (G->dist[w] > d) {
                    G->dist[w] = d;
                    G->path[w] = v;

                    queue_remove(&queue, w);
                    queue_push(&queue, w, d);
                }

                e = e->next;
            }
        }
    }

    int main()
    {
        int t;

        scanf("%d", &t);

        while (t--) {
            Graph *G;
            int v, e, s;

            scanf("%d %d", &v, &e);

            G = graph_new(v);

            for (int i = 0; i < e; i++) {
                int u, v, w;

                scanf("%d %d %d", &u, &v, &w);
                graph_edge(G, u - 1, v - 1, w);
            }

            scanf("%d", &s);
            dijkstra(G, s - 1);

            for (int i = 0; i < G->v; i++) {
                if (i != s - 1) {
                    printf("%d ", G->dist[i]);
                }
            }

            puts("");
            graph_delete(G);
        }

        return 0;
    }

1 Ответ

0 голосов
/ 16 ноября 2018

queue_push() не удается правильно вставить новый узел.

Обновлен только один узел .next.Обычно 2 узла нуждаются в обновлении члена .next.Один в исходном списке (предшествующий местоположению нового узла) и новый.


Я считаю создание временного узла перед списком superhead, упрощающим код.

void queue_push(Queue **head, int d, int p) {
  Queue *q = queue_new(d, p);

  Queue superhead; // Only superhead.next member important.
  superhead.next = *head;  
  Queue *previous = &superhead;

  while (previous->next && previous->next->priority < p) {
    previous = previous->next;
  }

  q->next = previous->next;
  previous->next = q;
  *head = superhead.next;
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...