How to implement a linked list in C?

后端 未结 14 824
予麋鹿
予麋鹿 2020-12-06 02:49

I am creating a linked list as in the previous question I asked. I have found that the best way to develop the linked list is to have the head and tail in another structure.

相关标签:
14条回答
  • 2020-12-06 03:30

    If you are looking to better understand the basics of linked lists, take a look at the following document:

    http://cslibrary.stanford.edu/103/LinkedListBasics.pdf

    0 讨论(0)
  • 2020-12-06 03:31

    If you are learning C pointer theory this is a good exercise. Otherwise, it feels like too much indirection for code that is not generic (as in a library).

    Instead of allocating a static 128 byte character string, you might want to do some more pointer practice and use an allocated exact length string that you clean up at exit.

    Academically, kungfucraigs' structure looks more generic then the one you have defined.

    0 讨论(0)
  • 2020-12-06 03:31

    A demo for Singly Linked List. If you prefer, try to check Circular Linked List and Doubly Linked List.

    #include <stdio.h>
    #include <stdlib.h>
    
    
    typedef struct node {
        int val;
        struct node * next;
    } node_t;
    
    
    // Iterating over a list
    void
    print_list(node_t *head)
    {
        node_t *current = head;
    
        while(current != NULL)
        {
            printf("%d\n", current->val);
            current = current->next;
        }
    }
    
    
    // Adding an item to the end of the list
    void
    push_end(node_t *head, int val)
    {
        node_t *current = head;
        while (current->next != NULL)
        {
            current = current->next;
        }
    
        current->next = malloc(sizeof(node_t));
        current->next->val = val;
        current->next->next = NULL;
    }
    
    // Adding an item to the head of the list
    void
    push_head(node_t **head, int val)
    {
        node_t *new_node = NULL;
    
        new_node = malloc(sizeof(node_t));
        new_node->val = val;
        new_node->next = *head;
    
        *head = new_node;
    }
    
    // Removing the head item of the list
    int
    pop_head(node_t **head)
    {
        int retval = -1;
        node_t *next_node = NULL;
    
        if (*head == NULL) {
            return -1;
        }
    
        next_node = (*head)->next;
        retval = (*head)->val;
        free(*head);
        *head = next_node;
    
        return retval;
    }
    
    // Removing the last item of the list
    int
    pop_last(node_t *head)
    {
        int retval = 0;
        node_t *current = NULL;
    
        if (head->next == NULL) {
            retval = head->val;
            free(head);
            return retval;
        }
    
        /* get to the second to last node in the list */
        current = head;
        while (current->next->next != NULL) {
            current = current->next;
        }
    
        /* now current points to the second to last item of the list.
           so let's remove current->next */
        retval = current->next->val;
        free(current->next);
        current->next = NULL;
    
        return retval;
    }
    
    // Removing a specific item
    int
    remove_by_index(node_t **head, int n)
    {
        int i = 0;
        int retval = -1;
        node_t *current = *head;
        node_t *temp_node = NULL;
    
        if (n == 0) {
            return pop_head(head);
        }
    
        for (i = 0; i < n - 1; i++) {
            if (current->next == NULL) {
                return -1;
            }
            current = current->next;
        }
    
        temp_node = current->next;
        retval = temp_node->val;
        current->next = temp_node->next;
        free(temp_node);
    
        return retval;
    }
    
    
    int
    main(int argc, const char *argv[])
    {
        int i;
        node_t * testnode;
    
        for (i = 0; i < argc; i++)
        {
            push_head(&testnode, atoi(argv[i]));
        }
    
        print_list(testnode);
    
        return 0;
    }
    
    // http://www.learn-c.org/en/Linked_lists
    // https://www.geeksforgeeks.org/data-structures/linked-list/
    
    0 讨论(0)
  • 2020-12-06 03:32

    I think u first need to Imagin back-end. Code are nothing to important. Go here and visualize back-end basic c code of all insertion. 1) Insertion at beginning Visit and scroll to get every instruction execution on back- end And u need front and imagin Go here Back end imagin

    And All other possible insertion here.

    And important thing u can use this way.

    struct Node{
    int data;//data field
    struct Node*next;//pointer field
    };
    

    struct Node*head,*tail; // try this way

    or short cut

    struct Node{
    int data;//data field
    struct Node*next;//pointer field
    }*head,*tail; //global root pointer
    

    And

    << Click >> To visualize other linked list problem.

    Thanks.

    0 讨论(0)
  • In memory your items are linked by pointers in the list structure

    item1 -> item2

    Why not make the list structure part of your item?

    Then you allocate a product item, and the list structure is within it.

    typedef struct product_data 
    {
        int product_code;
        char product_name[PRODUCT_NAME_LEN];
        int product_cost;
        struct list_t list; // contains the pointers to other product data in the list
    }product_data_t;
    
    0 讨论(0)
  • 2020-12-06 03:34

    The linked list implementation inspired by the implementation used in the Linux kernel:

    // for 'offsetof', see: https://stackoverflow.com/q/6433339/5447906.
    #include <stddef.h>
    
    // See: https://stackoverflow.com/q/10269685/5447906.
    #define CONTAINER_OF(ptr, type, member) \
        ( (type *) ((char *)(ptr) - offsetof(type, member)) )
    
    // The macro can't be used for list head.
    #define LIST_DATA(ptr, type, member) \
        CONTAINER_OF(ptr, type, member);
    
    // The struct is used for both: list head and list nodes.
    typedef struct list_node
    {
        struct list_node *prev, *next;
    }
    list_node;
    
    // List heads must be initialized by this function.
    // Using the function for list nodes is not required.
    static inline void list_head_init(list_node *node)
    {
        node->prev = node->next = node;
    }
    
    // The helper function, mustn't be used directly.
    static inline void list_add_helper(list_node *prev, list_node *next, list_node *nnew)
    {
        next->prev = nnew;
        nnew->next = next;
        nnew->prev = prev;
        prev->next = nnew;
    }
    
    // 'node' must be a list head or a part of a list.
    // 'nnew' must not be a list head or a part of a list. It may
    //   be uninitialized or contain any data (even garbage).
    static inline void list_add_after(list_node *node, list_node *nnew)
    {
        list_add_helper(node, node->next, nnew);
    }
    
    // 'node' must be a list head or a part of a list.
    // 'nnew' must not be a list head or a part of a list. It may
    //   be uninitialized or contain any data (even garbage).
    static inline void list_add_before(list_node *node, list_node *nnew)
    {
        list_add_helper(node->prev, node, nnew);
    }
    
    // 'node' must be part of a list.
    static inline list_node *list_del(list_node *node)
    {
        node->prev->next = node->next;
        node->next->prev = node->prev;
        return node->prev;
    }
    

    Example of usage:

    #include <stdio.h>
    
    // The struct must contain 'list_node' to be able to be inserted to a list
    typedef struct
    {
        int       data;
        list_node node;
    }
    my_struct;
    
    // Convert 'list_node *' to 'my_struct*' that contains this 'list_node'
    static inline my_struct* get_my_struct(list_node *node_ptr)
    {
        return LIST_DATA(node_ptr, my_struct, node);
    }
    
    void print_my_list(list_node *head)
    {
        printf("list: {");
        for (list_node *cur = head->next; cur != head; cur = cur->next)
        {
            my_struct *my = get_my_struct(cur);
            printf(" %d", my->data);
        }
        printf(" }\n");
    }
    
    // Print 'cmd' and run it. Note: newline is not printed.
    #define TRACE(cmd) \
        (printf("%s -> ", #cmd), (cmd))
    
    int main()
    {
        // The head of the list and the list itself. It doesn't contain any data.
        list_node head;
        list_head_init(&head);
    
        // The list's nodes, contain 'int' data in 'data' member of 'my_struct'
        my_struct el1 = {1};
        my_struct el2 = {2};
        my_struct el3 = {3};
    
        print_my_list(&head); // print initial state of the list (that is an empty list)
    
        // Run commands and print their result.
        TRACE( list_add_after (&head    , &el1.node) ); print_my_list(&head);
        TRACE( list_add_after (&head    , &el2.node) ); print_my_list(&head);
        TRACE( list_add_before(&el1.node, &el3.node) ); print_my_list(&head);
        TRACE( list_del       (head.prev)            ); print_my_list(&head);
        TRACE( list_add_before(&head    , &el1.node) ); print_my_list(&head);
        TRACE( list_del       (&el3.node)            ); print_my_list(&head);
    
        return 0;
    }
    

    The result of execution of the code above:

    list: { }
    list_add_after (&head , &el1.node) -> list: { 1 }
    list_add_after (&head , &el2.node) -> list: { 2 1 }
    list_add_before(&el1.node, &el3.node) -> list: { 2 3 1 }
    list_del (head.prev) -> list: { 2 3 }
    list_add_before(&head , &el1.node) -> list: { 2 3 1 }
    list_del (&el3.node) -> list: { 2 1 }
    

    http://coliru.stacked-crooked.com/a/6e852a996fb42dc2

    Of course in real life you will most probably use malloc for list elements.

    0 讨论(0)
提交回复
热议问题