Home > Blockchain >  Creating a linked list without malloc in C
Creating a linked list without malloc in C

Time:03-24

I'm trying to create a linked list without dynamic allocation and fill it with number from 0-8 and then print them, but everytime I try it gives me random values.

#include <stdio.h>

struct listNode
{
    int value;
    struct listNode *next;
};

int main()
{
    struct listNode list;
    struct listNode *head = &list;
    int i;

    for (i = 0; i < 9; i  )
    {
        list.value = i;
        struct listNode new;
        list.next = &new;
        list = *(list.next);
    }

    for (i = 0; i < 9; i  )
    {
        printf("%d, ", (*head).value);
        head = (*head).next;
    }

    return 0;
}

It looks like it should be working but it doesn't, what am I missing?

CodePudding user response:

To allocate nodes without malloc, there is also a possibility to use the stack for this purpose. This is only interesting as a little exercise, but would be a bad idea in real code.

The idea is that whenever a new node must be allocated, you make a recursive call, and then continue the rest of the program's logic there without returning from that recursive call. Only when the program can exit, you would unwind out of recursion. This is not very handy to work with, leads to waste of memory, as not only the allocated nodes are on that stack, but also some other data that has no more use. Moreover, there is no reuse of space whenever a node is deleted from the list unless you also maintain a free list.

So again, this is not best practice, and one should really use the heap for such dynamic allocation. I hope this disclaimer was strong enough to still allow me to post this piece of code that implements this idea:

#include <stdio.h>

struct listNode
{
    int value;
    struct listNode *next;
};

void printList(struct listNode *head) {
    while (head != NULL) {
        printf("%d -> ", head->value);
        head = head->next;
    }
    printf("NULL\n");
}

void deleteFromList(struct listNode **headPtr, struct listNode **tailPtr, int value) {
    while (*headPtr != NULL && (*headPtr)->value == value) {
        *headPtr = (*headPtr)->next;
    }
    if (*headPtr == NULL) {
        *tailPtr = NULL;
        return;
    }
    struct listNode *current = *headPtr;
    while (current->next != NULL) {
        if (current->next->value == value) {
            current->next = current->next->next;
        } else {
            current = current->next;
        }
    }
    *tailPtr = current;
}

void appendToList(struct listNode **headPtr, struct listNode **tailPtr, struct listNode *new) {
    new->next = NULL;
    if (*tailPtr != NULL) {
        (*tailPtr)->next = new;
    } else {
        *headPtr = new;
    }
    *tailPtr = new;
}

// This is the main program's logic, but it gets called recursively whenever a node
//   is inserted into the list:
void menu(struct listNode *head, struct listNode *tail) {
    struct listNode new;
    char choice;
    while (1) {
        printf("[i]nsert, [d]elete, [p]rint, [e]xit: ");
        scanf(" %c", &choice);
        switch(choice) {
            case 'p':
                printList(head);
                break;
            case 'i':
                printf("insert value: ");
                scanf(" %d", &new.value);
                appendToList(&head, &tail, &new);
                menu(head, tail); // Recursion
                return;
            case 'd':
                printf("delete value: ");
                scanf(" %d", &new.value);
                deleteFromList(&head, &tail, new.value); 
                break;
            case 'e':
                return;
        } 
    }
}
    
int main()
{
    menu(NULL, NULL);
    return 0;
}
  • Related