【发布时间】:2019-04-19 23:04:30
【问题描述】:
我的怀疑只是关于指针,如果我们使用 *head,这里 head 是一个指向 Queue 的双指针,而不是我们访问 main 内部的位置(或传递的地址)但是当我们简单地使用 head 时我们只在当前函数中使用标题,它将保存指向 Queue 的指针的地址,现在当我们这样做时 head=&(*head)->next 因为 (*head)->next 本身就是一个地址,而当我们之前使用 &这将创建一个单独的块,并将创建一个内存块并保存 (*head)->next 的地址,我们将该地址分配给 head
我有这个疑问,因为它就像一个两步过程,我们不能直接把 (*head)->next 放在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;
}
【问题讨论】:
-
while (*head && (*head)->priority < p) { head = &(*head)->next; }应该遍历列表,而不是更改head。 -
什么是地址`&(*head)->next`计算机如何生成地址地址而不存储(*head)->next 任何应该有一些内存块的地方我们可以存储(*head)->next 的地址,现在该内存块的地址将分配给
head,如果发生这种情况,那么每当循环运行时,计算机会将所有中间体的地址存储在同一块或不同的内存块中跨度> -
在
G = malloc(sizeof(*G))中很好地使用sizeof(*G)而不是malloc(sizeof(Graph))。
标签: c pointers memory-management