Неверное представление списка смежности графа

0

Я пытаюсь представить граф, используя представление списка смежности графиков. Мой код правильно компилируется, но показывает неправильный результат, я не могу найти логическую несогласованность в моем коде. Это пример ввода и вывода

Enter the number of Vertices 
 4

Enter the number of Edges
 6

Введите края

0 1

1 2

2 3

3 0

0 2

1 3

Список вершин головы вершины 0 → 0-> 2

Список адгезии головы вершины 1 → 1-> 3

Список адгезии головы вершины 2 → 2

Список адгезии головы вершины 3 → 3

Заметим здесь, что 0 также связано с 1

2 также соединен с 1 и 0

struct grnode {

long long num;
struct grnode *next;
};

struct graph {

long long v;
long long e;
struct grnode *adj;
};

struct graph *adjlistgr(){

long long i,x,y;
struct grnode *temp;
struct graph *g = (struct graph*)malloc(sizeof(struct graph));
if (!g) {
    printf("memory error");
    return;
}
// here we scanf  the num of vertices and edges
printf("Enter the number of Vertices \n");
scanf("%lld", &g->v);
printf("Enter the number of Edges\n");
scanf("%lld", &g->e);
g->adj = malloc(g->v*sizeof(struct grnode));
for (i = 0; i < g->v; i++)
{

    g->adj[i].num = i;
    g->adj[i].next = &g->adj[i];
}
printf("Enter the Edges\n");
for (i = 0; i < g->e;i++)
{   // now we scan the edges

    scanf("%lld %lld", &x,&y);

    temp = (struct grnode*)malloc( sizeof( struct grnode*));
    temp->num = y;
    temp->next = &g->adj[x];
    g->adj[x].next = temp;
    temp = (struct grnode*)malloc( sizeof( struct grnode*));
    temp->num = y;
    temp->next = &g->adj[y];
    g->adj[y].next = temp;
}return g;
}

 void printgraph(struct graph* graph)
{                   

int n;                         
for (n = 0; n < graph->v; ++n)               
{                                      
    // struct grnode *pCrawl = graph->adj[n].num;
    struct grnode *temp;
    temp = (struct grnode*)malloc( sizeof( struct grnode*));
    temp->next=&graph->adj[n];
    temp=temp->next;
    printf("\n Adjacency list of vertex %d\n head ", n);
    long long s=temp->num;
    do 
    {
        printf("-> %d", temp->num);
        temp = temp->next;
    }while(temp->num!=s);
    printf("\n");
}}    
  int main(){      
  struct graph *mylist=adjlistgr();          
  printgraph(mylist);    
}
  • 0
    Обратите внимание, что 0 связан с 1, который не отображается, является одним из несоответствий с кодом
  • 1
    Если вы хотите уточнить свой вопрос, вы должны отредактировать его, чтобы сделать это, а не добавлять его в качестве комментария.
Показать ещё 4 комментария
Теги:
graph
adjacency-list

2 ответа

0
Лучший ответ

Помимо проблемы с распределением, ваша организация данных нуждается в переосмыслении.

У вас также есть неправильные представления о malloc. Например, вы выделяете память внутри функции печати. Эта функция должна просто проверять данные, а затем распечатывать их. Выделение не нужно. В вашем коде вы сразу же переписываете дескриптор в распределенные данные:

temp = (struct grnode*)malloc( sizeof( struct grnode*));
temp->next=&graph->adj[n];
temp=temp->next;

Это означает, что вы теряете доступ к новым данным (и не можете free его позже). Это нравится покупать дом и отбрасывать ключи. Достаточно сказать:

temp = &graph->adj[n];

Когда вы работаете с указателями, имейте в виду: указатель должен указывать на действительные данные или он должен быть NULL. Когда вы выделяете память, не меняйте дескриптор этой памяти и не забудьте free ее через этот дескриптор позже.

О вашем графике: у вас есть четыре узла. Эти узлы фиксируются после их инициализации. Вы не можете добавлять грани между ними, но вы не можете повторно использовать их для выполнения двойной обязанности как элементов того, что должно быть четырех независимых связанных списков. Это то, что хочет сделать ваш код.

Существует несколько способов описания смежности. Вы можете добавить матрицу к своему графику или создать краевую структуру, которая содержит два соединительных узла и организована графиком. Или вы можете создать связанный список связей для каждого узла. Выбери один.

Главное, что вам нужны две идеальные структуры данных для ваших узлов и ребер.

Изменить. Основываясь на вашей основной идее использования связанных списков для представления соединений, я применил простую структуру для однонаправленных графиков ниже. Вы можете видеть, что каждый grnode поддерживает свой собственный связанный список соединений grconn. Код также показывает, как очистить использованную память после ее использования.

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

struct grnode;
struct grconn;

struct grconn {                 /* Connection to node (linked list) */
    struct grnode *dest;
    struct grconn *next;
};

struct grnode {                 /* Node in graph */
    int id;
    struct grconn *conn;
};

struct graph {
    int nnode;
    struct grnode *node;
};



/*
 *      Create new connection to given node
 */
struct grconn *grconn_new(struct grnode *nd)
{
    struct grconn *c = malloc(sizeof(*c));

    if (c) {
        c->dest = nd;
        c->next = NULL;
    }

    return c;
}

/*
 *      Clean up linked list of connections
 */
void grconn_delete(struct grconn *c)
{ 
    while (c) {
        struct grconn *p = c->next;

        free(c);
        c = p;
    }
}

/*
 *      Print connectivity list of a node
 */
void grnode_print(struct grnode *nd)
{
    struct grconn *c;

    printf("%d:", nd->id);

    c = nd->conn;
    while (c) {
        printf(" %d", c->dest->id);
        c = c->next;
    }

    printf("\n");
}



/*
 *      Create new graph with given number of nodes
 */
struct graph *graph_new(int n)
{
    struct graph *g = malloc(sizeof(*g));
    int i;

    if (g == NULL) return g;

    g->nnode = n;
    g->node = malloc(n * sizeof(*g->node));
    if (g->node == NULL) {
        free(g);
        return NULL;
    }

    for (i = 0; i < n; i++) {
        g->node[i].id = i;
        g->node[i].conn = NULL;
    }

    return g;
}

/*
 *      Delete graph and all dependent data
 */
void graph_delete(struct graph *g)
{
    int i;

    for (i = 0; i < g->nnode; i++) {
        grconn_delete(g->node[i].conn);
    }

    free(g->node);
    free(g);
}

/*
 *      Print connectivity of all nodes in graph
 */
void graph_print(struct graph *g)
{
    int i;

    for (i = 0; i < g->nnode; i++) {
        grnode_print(&g->node[i]);
    }
}

/*
 *      Create one-way connection from node a to node b
 */
void graph_connect(struct graph *g, int a, int b)
{
    struct grnode *nd;
    struct grconn *c;

    if (a < 0 || a >= g->nnode) return;
    if (b < 0 || b >= g->nnode) return;

    nd = &g->node[a];
    c = grconn_new(&g->node[b]);

    c->next = nd->conn;
    nd->conn = c;
}

/*
 *      Create two-way connection between nodes a and b
 */
void graph_connect_both(struct graph *g, int a, int b)
{
    graph_connect(g, a, b);
    graph_connect(g, b, a);
}



/*
 *      Example client code
 */
int main()
{
    struct graph *g = graph_new(4);

    graph_connect_both(g, 0, 1);
    graph_connect_both(g, 1, 2);
    graph_connect_both(g, 2, 3);
    graph_connect_both(g, 0, 2);
    graph_connect_both(g, 1, 3);

    graph_print(g);

    graph_delete(g);

    return 0;
}
  • 0
    Да, сэр, я понял, что мой код просто заменяет последний элемент в связанном списке моим текущим вводом для края, у меня неверное представление о связанном списке, я просто хотел спросить, что я могу сделать, чтобы выделить новое добавление памяти к связанному списку каждый раз, когда я добавляю ребро, например, ребра 0 1 и 0 2 и 0 3 будут интерпретироваться моим кодом как 0-> 3, что нужно сделать, чтобы оно стало 0 -> 1-> 2 -> 3 Спасибо
  • 0
    Большое спасибо, сэр, ваша помощь сделала мой день, я, кажется, наконец-то понял идею списка смежности. У меня все еще много сомнений, и я буду над этим работать, Большое спасибо, сэр.
0

Выражение malloc( sizeof( struct grnode*)) выделяет указатель и возвращает вам указатель на выделенный указатель. Если вы не используете это как указатель на указатель, как вы этого не сделаете, у вас есть неопределенное поведение.

Я подозреваю, что вы действительно хотите malloc( sizeof( struct grnode)).

Кстати, в C вы не должны бросать результат malloc. И в C++ вы все равно не должны использовать malloc.

  • 0
    Да, сэр, я понял, что мой код просто заменяет последний элемент в связанном списке моим текущим вводом для края, у меня неверное представление о связанном списке, я просто хотел спросить, что я могу сделать, чтобы выделить новое добавление памяти к связанному списку каждый раз, когда я добавляю ребро, например, ребра 0 1 и 0 2 и 0 3 будут интерпретироваться моим кодом как 0-> 3, что нужно сделать, чтобы оно стало 0 -> 1-> 2 -> 3 Спасибо -

Ещё вопросы

Сообщество Overcoder
Наверх
Меню