Я изучаю связанный список. Здесь я сначала пытаюсь добавить узел, поэтому я создал функцию структуры для добавления, но я не знаю, почему она не работает, она дает только этот вывод без добавления

7 11 66 После введения 7 11 66

А также, пожалуйста, скажите мне, есть ли способ вставить элемент в связанный список.

// inserting element on first
#include<stdio.h>
#include<stdlib.h>

struct Node
{
    int data;
    struct Node * next;
};

void link_list_tranversal(struct Node *ptr){
    while (ptr!=NULL)
    {
        printf("%d\n",ptr->data);
        ptr=ptr->next;
    }
    
   
}


struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

int main(){
    struct Node*head;
    struct Node*second;
    struct Node*third;
    head =(struct Node *) malloc(sizeof(struct Node));
    second =(struct Node *) malloc(sizeof(struct Node));
    third =(struct Node *) malloc(sizeof(struct Node));
   // linking first and secend node
    head ->data=7;
    head->next=second;
    // linking secend and third node
    second->data=11;
    second->next=third;
    // terminate the list at the third
    third->data=66;
    third->next=NULL;
    link_list_tranversal(head);

    insert_at_first(head,56);
    printf("After insretion\n ");
    link_list_tranversal(head);
    return 0;
}
0
ANUP KUMAR 20 Сен 2022 в 21:57
Что возвращает insert_at_first ?
 – 
Some programmer dude
20 Сен 2022 в 22:00

4 ответа

Лучший ответ

После insert_at_first(head,56); вы создали новый узел, но head теперь указывает на второй узел в списке, и вы потеряли след вновь созданного узла. Самое простое решение: head = insert_at_first(head,56);. Вы также можете передать &head и позволить функции обновить head.

1
William Pursell 20 Сен 2022 в 22:00

Вам нужно обновить указатель, который вы сохраняете в head после вызова insert_at_first.

// inserting element on first
#include<stdio.h>
#include<stdlib.h>

struct Node
{
    int data;
    struct Node * next;
};

void link_list_tranversal(struct Node *ptr){
    while (ptr!=NULL)
    {
        printf("%d\n",ptr->data);
        ptr=ptr->next;
    }
    
   
}


struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

int main(){
    struct Node*head;
    struct Node*second;
    struct Node*third;
    head =(struct Node *) malloc(sizeof(struct Node));
    second =(struct Node *) malloc(sizeof(struct Node));
    third =(struct Node *) malloc(sizeof(struct Node));
   // linking first and secend node
    head ->data=7;
    head->next=second;
    // linking secend and third node
    second->data=11;
    second->next=third;
    // terminate the list at the third
    third->data=66;
    third->next=NULL;
    link_list_tranversal(head);

    head = insert_at_first(head,56);
    printf("After insretion\n ");
    link_list_tranversal(head);
    return 0;
}

Выход:

7
11
66
After insretion
 56
7
11
66
1
JRose 20 Сен 2022 в 22:01

Функция insert_at_first возвращает новое значение указателя, указывающего на головной узел. Вам нужно присвоить возвращаемое значение указателю head, чтобы обновить его.

head = insert_at_first(head,56);

Также нет особого смысла размещать узлы в main, когда у вас уже есть функция insert_at_first

Вы могли бы сначала написать, например

struct Node *head = NULL;

head = insert_at_first( head, 66 );
head = insert_at_first( head, 11 );
head = insert_at_first( head, 7 );
head = insert_at_first( head, 56 );

Также, поскольку функция link_list_tranversal не изменяет выводимого списка, ее параметр должен быть объявлен с квалификатором const.

void link_list_tranversal( const struct Node *ptr );

Обратите внимание на то, что это определение функции

struct Node * insert_at_first(struct Node *head,int data){
    struct Node *ptr=(struct Node *)malloc(sizeof(struct Node));
    ptr->next=head;
    ptr->data=data;
    return ptr;
}

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

Лучше объявить и определить функцию следующим образом

int insert_at_first( struct Node **head, int data )
{
    struct Node *ptr = malloc( *ptr );
    int success = ptr != NULL;

    if ( success )
    { 
       ptr->next = *head;
       ptr->data = data;
       *head = ptr;
    }

    return success;
}

И функция может быть вызвана, например, как

struct Node *head = NULL;

insert_at_first( &head, 66 );

Или

struct Node *head = NULL;

if ( !insert_at_first( &head, 66 ) )
{
    puts( "Error. No enough memory" );
} 
0
Vlad from Moscow 20 Сен 2022 в 23:14

Обычный подход при обучении состоит в том, чтобы добавить больше кода, а затем добавить еще.

Ниже приведен эквивалент всей вашей программы, но с гораздо меньшим количеством строк кода (но большим количеством комментариев).

Пожалуйста, прочитайте это и подумайте, что и почему в каждой строке.

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

typedef struct Node { // Using 'typedef' saves LOTS of typing (and reading)
    int data; // for now, just one integer
    struct Node *next;
} node_t; // conventional naming of a 'type' with "_t" suffix

int mmain() {
    int data[] = { 66, 11, 7, 56 }; // your data in compact form

    node_t *head = NULL; // ALWAYS initialise variable. Don't let random values happen
    for( int i = 0; i < sizeof data/sizeof data[0]; i++ ) { // loop to create LL
        // use 'calloc()'. explained below
        // do not cast the return pointer from malloc/calloc
        node_t *pn = calloc( 1, sizeof *pn );

        // malloc/calloc can fail. Halt processing immediately.
        if( pn == NULL ) {
            fprintf( stderr, "panic! calloc failed.\n" );
            exit( 1 );
        }
        pn->data = data[i]; // for now, just one integer

        pn->next = head; // two lines of code "prepend" the new node
        head = pn;

        // traverse here showing growth
        for( pn = head; pn; pn = pn->next )
            printf( "%d  ", pn->data );
        putchar( '\n' );
    }

    // Avoid memory leaks
    // Don't forget to release heap memory when no longer needed.
    while( head ) {
        node_t *pn = head; // node to be free'd
        head = head->next; // remember next
        free( pn ); // OFF WITH ITS HEAD! 
    }

    return 0;
}

Выход

66
11  66
7  11  66
56  7  11  66

Я рекомендую использовать calloc() вместо malloc() при разработке кода, который будет расти. Сейчас полезная нагрузка, которую несет каждый узел, представляет собой одно целое число. В гуще событий можно добавить больше элементов в структуру узла (большая полезная нагрузка) но не устанавливать для каждого из новых элементов известное значение. Использование calloc() гарантирует, что все байты будут последовательно инициализированы нулем. Затем при тестировании вы получаете стабильное поведение (работающее или нет), что упрощает отслеживание ошибок.

Обратите внимание, что «предварительное добавление» к LL — слишком тривиальная операция, чтобы «разбиваться» на собственную функцию. «Добавление» не намного сложнее, но может оправдать функцию в соответствии с вашими вкусами.

Вот снова тот же код, без комментариев, для сравнения.

typedef struct Node {
    int data;
    struct Node *next;
} node_t;

int main() {
    int data[] = { 66, 11, 7, 56 };

    node_t *head = NULL;
    for( int i = 0; i < sizeof data/sizeof data[0]; i++ ) {
        node_t *pn = calloc( 1, sizeof *pn );
        if( pn == NULL ) {
            fprintf( stderr, "panic! calloc failed.\n" );
            exit( 1 );
        }
        pn->data = data[i];
        pn->next = head;
        head = pn;

        // traversal for debugging
        for( pn = head; pn; pn = pn->next )
            printf( "%d  ", pn->data );
        putchar( '\n' );
    }

    while( head ) {
        node_t *pn = head;
        head = head->next;
        free( pn );
    }

    return 0;
}

Даже если программа создает новые узлы в разных местах, необходимо учитывать полезную нагрузку. Не пишите тривиальную функцию insert(), которая корректирует два указателя, но получает 27 параметров в вызове функции.

0
Fe2O3 21 Сен 2022 в 00:02