Advertisement
Guest User

Untitled

a guest
Apr 4th, 2020
340
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C 5.77 KB | None | 0 0
  1. Let's define a linked list node:
  2.  
  3. typedef struct node {
  4.    int val;
  5.    struct node * next;
  6. } node_t;
  7.  
  8. Notice that we are defining the struct in a recursive manner, which is possible in C. Let's name our node type node_t.
  9.  
  10. Now we can use the nodes. Let's create a local variable which points to the first item of the list (called head).
  11.  
  12. node_t * head = NULL;
  13. head = (node_t *) malloc(sizeof(node_t));
  14. if (head == NULL) {
  15.    return 1;
  16. }
  17.  
  18. head->val = 1;
  19. head->next = NULL;
  20.  
  21. We've just created the first variable in the list. We must set the value, and the next item to be empty, if we want to finish populating the list. Notice that we should always check if malloc returned a NULL value or not.
  22.  
  23. To add a variable to the end of the list, we can just continue advancing to the next pointer:
  24.  
  25. node_t * head = NULL;
  26. head = (node_t *) malloc(sizeof(node_t));
  27. head->val = 1;
  28. head->next = (node_t *) malloc(sizeof(node_t));
  29. head->next->val = 2;
  30. head->next->next = NULL;
  31.  
  32. This can go on and on, but what we should actually do is advance to the last item of the list, until the next variable will be NULL.
  33. Iterating over a list
  34.  
  35. Let's build a function that prints out all the items of a list. To do this, we need to use a current pointer that will keep track of the node we are currently printing. After printing the value of the node, we set the current pointer to the next node, and print again, until we've reached the end of the list (the next node is NULL).
  36.  
  37. void print_list(node_t * head) {
  38.     node_t * current = head;
  39.  
  40.     while (current != NULL) {
  41.         printf("%d\n", current->val);
  42.         current = current->next;
  43.     }
  44. }
  45.  
  46. Adding an item to the end of the list
  47.  
  48. To iterate over all the members of the linked list, we use a pointer called current. We set it to start from the head and then in each step, we advance the pointer to the next item in the list, until we reach the last item.
  49.  
  50. void push(node_t * head, int val) {
  51.     node_t * current = head;
  52.     while (current->next != NULL) {
  53.         current = current->next;
  54.     }
  55.  
  56.     /* now we can add a new variable */
  57.     current->next = (node_t *) malloc(sizeof(node_t));
  58.     current->next->val = val;
  59.     current->next->next = NULL;
  60. }
  61.  
  62. The best use cases for linked lists are stacks and queues, which we will now implement:
  63. Adding an item to the beginning of the list (pushing to the list)
  64.  
  65. To add to the beginning of the list, we will need to do the following:
  66.  
  67.     Create a new item and set its value
  68.     Link the new item to point to the head of the list
  69.     Set the head of the list to be our new item
  70.  
  71. This will effectively create a new head to the list with a new value, and keep the rest of the list linked to it.
  72.  
  73. Since we use a function to do this operation, we want to be able to modify the head variable. To do this, we must pass a pointer to the pointer variable (a double pointer) so we will be able to modify the pointer itself.
  74.  
  75. void push(node_t ** head, int val) {
  76.     node_t * new_node;
  77.     new_node = (node_t *) malloc(sizeof(node_t));
  78.  
  79.     new_node->val = val;
  80.     new_node->next = *head;
  81.     *head = new_node;
  82. }
  83.  
  84. Removing the first item (popping from the list)
  85.  
  86. To pop a variable, we will need to reverse this action:
  87.  
  88.     Take the next item that the head points to and save it
  89.     Free the head item
  90.     Set the head to be the next item that we've stored on the side
  91.  
  92. Here is the code:
  93.  
  94. int pop(node_t ** head) {
  95.    int retval = -1;
  96.    node_t * next_node = NULL;
  97.  
  98.    if (*head == NULL) {
  99.        return -1;
  100.    }
  101.  
  102.    next_node = (*head)->next;
  103.    retval = (*head)->val;
  104.    free(*head);
  105.    *head = next_node;
  106.  
  107.    return retval;
  108. }
  109.  
  110. Removing the last item of the list
  111.  
  112. Removing the last item from a list is very similar to adding it to the end of the list, but with one big exception - since we have to change one item before the last item, we actually have to look two items ahead and see if the next item is the last one in the list:
  113.  
  114. int remove_last(node_t * head) {
  115.    int retval = 0;
  116.    /* if there is only one item in the list, remove it */
  117.    if (head->next == NULL) {
  118.        retval = head->val;
  119.        free(head);
  120.        return retval;
  121.    }
  122.  
  123.    /* get to the second to last node in the list */
  124.    node_t * current = head;
  125.    while (current->next->next != NULL) {
  126.        current = current->next;
  127.    }
  128.  
  129.    /* now current points to the second to last item of the list, so let's remove current->next */
  130.     retval = current->next->val;
  131.     free(current->next);
  132.     current->next = NULL;
  133.     return retval;
  134.  
  135. }
  136.  
  137. Removing a specific item
  138.  
  139. To remove a specific item from the list, either by its index from the beginning of the list or by its value, we will need to go over all the items, continuously looking ahead to find out if we've reached the node before the item we wish to remove. This is because we need to change the location to where the previous node points to as well.
  140.  
  141. Here is the algorithm:
  142.  
  143.    Iterate to the node before the node we wish to delete
  144.    Save the node we wish to delete in a temporary pointer
  145.    Set the previous node's next pointer to point to the node after the node we wish to delete
  146.     Delete the node using the temporary pointer
  147.  
  148. There are a few edge cases we need to take care of, so make sure you understand the code.
  149.  
  150. int remove_by_index(node_t ** head, int n) {
  151.     int i = 0;
  152.     int retval = -1;
  153.     node_t * current = *head;
  154.     node_t * temp_node = NULL;
  155.  
  156.     if (n == 0) {
  157.         return pop(head);
  158.     }
  159.  
  160.     for (i = 0; i < n-1; i++) {
  161.         if (current->next == NULL) {
  162.             return -1;
  163.         }
  164.         current = current->next;
  165.     }
  166.  
  167.     temp_node = current->next;
  168.     retval = temp_node->val;
  169.     current->next = temp_node->next;
  170.     free(temp_node);
  171.  
  172.     return retval;
  173.  
  174. }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement