Как построить односвязный список из массива в C - PullRequest
2 голосов
/ 02 октября 2019

Я изучаю односвязные списки на C и пытаюсь связать компоненты массива. Я написал несколько строк кода, но он не дает требуемых результатов, т.е. создание и печать связанного списка из массива. Может кто-нибудь объяснить, почему это не работает? Спасибо

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

typedef struct list
{
int data;
struct list *next;
}
list;

list *createlinkedlist(int *arr);

void printlist(list * head);

int main(void)
{
    int arr[]={1,2,3,4,5};
    list *head=NULL;
    head = createlinkedlist(arr);
    printlist(head);

}

list *createlinkedlist(int *arr)
{
    list *head=NULL;
    list *temp=NULL;
    list *p=NULL;

    for (int j=0, O=sizeof(arr); j<O; j++)
        {
            temp= (list*)malloc(sizeof(list));
            temp->next = NULL;

        if(head == NULL)
            head=temp;
        else
        {
            p=head;
            while(p->next!=NULL)
            {
                p=p->next;
            }
            p->next = temp;
        }
    }
return head;
}


void printlist(list *head)
{
    list * p = head;
    while (p !=NULL)
    {
        printf("%d\n", p->data);
        p = p->next;
    }
}

Ответы [ 2 ]

1 голос
/ 02 октября 2019

Две проблемы,

  1. Массив, переданный функции, распадается на указатель.

    for (int j=0, O=sizeof(arr); j<O; j++)
    

    Здесь вы зацикливаетесь до размера указателя, а не до размера фактического массива.

    Передайте размер массива из main.

     list *createlinkedlist(int *arr, int length); //prototype becomes
     head = createlinkedlist(arr, sizeof (arr)); // function call becomes
     for (int j=0; j<length; j++) //for loop becomes
    
  2. Вы не сохраняете содержимое массива в связанный список.

        temp= (list*)malloc(sizeof(list));
        temp->data = arr[j]; //store the content into list
        temp->next = NULL;
    
0 голосов
/ 02 октября 2019
#include <stdio.h>
#include <stdlib.h>

typedef struct list
{
    int data;
    struct list* next;
}
list;

list* createlinkedlist(int* arr, int length);

void printlist(list* head);

void deleteList(list* _list, int length);

int main(void)
{
    int arr[] = { 1,2,3,4,5 };
    list* head = NULL;
    head = createlinkedlist(arr, 5);

    // Result is '1\n,2\n,3\n,4\n,5\n'
    printlist(head);
    deleteList(head, 5);

    // Below value is garbage
    printf("%p\n", head->next);
}

void deleteList(list* p, int length)
{
    list** nodeArr = (list **)malloc(sizeof(list*) * length);

    for (int i = 0; p != NULL; i++, p = p->next)
    {
        nodeArr[i] = p;
    }

    for (int i = 0; i <= sizeof(nodeArr); ++i)
    {
        free(nodeArr[i]);
    }

    free(nodeArr);
}

list* createlinkedlist(int* arr, int length)
{
    list* head = NULL;
    list* temp = NULL;
    list* p = NULL;

    // repeat until j == length
    for (int j = 0; j < length; j++)
    {
        temp = (list*) malloc(sizeof(list));

        // assign value of arr[j]
        temp->data = arr[j];

        temp->next = NULL;

        if (head == NULL)
            head = temp;
        else
        {
            p = head;
            while (p->next != NULL)
            {
                p = p->next;
            }
            p->next = temp;
        }
    }
    return head;
}


void printlist(list* head)
{
    list* p = head;
    while (p != NULL)
    {
        printf("%d\n", p->data);
        p = p->next;
    }
}

Во-первых, вы не присвоили значение массива в списке.

Во-вторых, в то время как Statement должен повторяться до длины arr, и вы не передали длину arr.

('arr' - указатель типа int, указывающий на первый элемент (адрес 1) массива. Sizeof (arr) равен ' размер указателя типа int ', а не длина arr.)

Итак, вам нужно указать длину во втором аргументе 'createlinkedlist'.

Если вы исправите это, как в коде выше, это сработает.



Чтобы добавить это, Вы должны вызвать функцию 'free', чтобы вернуть использованную память после использования памяти кучи.

(а именно после использования malloc)

В этом случае вы можете определить функцию «deleteList», чтобы освободить все «следующее» в списке.


Или, если вы можете использовать c ++, вы можете определить деструктор в списке

typedef struct list
{
    int data;
    struct list* next;

    ~list (){
        delete next;
    }
}
list;

Вызов delete заголовка списка вызывает серию цепочек вызовов delete.

В этом случае вы должны использовать ключевое слово «delete» вместо функции «free»

...