1

I made a Doubly Linked List, but instead of manually assigning the values (10, 20, 30) I want to make a for loop and put the data that way to make it efficient. I did it in Singly Linked List but the same is not happening over here and only backward_traversing function works.

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

typedef struct Node
{
    int value;
    struct Node *next_link;
    struct Node *prev_link;
} Node;

Node *create_node(int value)
{
    Node *new_node = malloc(sizeof(Node));
    new_node->value = value;
    new_node->next_link = NULL;
    new_node->prev_link = NULL;

    return new_node;
}

void forward_traversing(Node *head)
{
    Node *temp = head;

    while (temp != NULL)
    {
        printf("%d ", temp -> value);
        temp = temp->next_link;
    }
    printf("\n");
}

void backward_traversing(Node *tail)
{
    Node *temp = tail;

    while (temp != NULL)
    {
        printf("%d ", temp->value);
        temp = temp->prev_link;
    }
    printf("\n");
}

void show_first(Node *head)
{
    printf("%d \n", head->value);
}

void show_last(Node *tail)
{
    printf("%d \n", tail->value);
}

int main()
{
    Node *head, *temp, *tail;

    for (int i = 0; i <= 25; i++){
        temp = create_node(i);
        temp -> next_link = head;
        head = temp;
    }
    
    forward_traversing(head);
    backward_traversing(tail);
    show_first(head);
    show_last(tail);
    
    return 0;
}
14
  • 3
    Create three functions: One to add a new node at the head of the list; One function to add a node to the tail of the list; And lastly one to insert a node behind (or before) another node. This will be greatly simplified if you separate the list and node structures. Implement and test the functions one by one. Once done, it's trivial to create a list via a loop, by just adding to the tail of the list inside the loop. Commented Oct 16, 2024 at 12:02
  • I might try the simplification method. Maybe first I'll try to get it as a array if that's bs then maybe transition it into a single linked list which will cause less load that array. Thanks! Commented Oct 16, 2024 at 12:13
  • 2
    Next tip: Whenever you have problems with things like linked lists, trees or other graphs or graph-like objects, use pen and paper. Try to come up with the algorithm by drawing and redrawing, and once you get it to work on paper implement it in code. If there's problems, step through the code line by line in a debugger while drawing what the code is doing. Compare your original drawings to the debug-drawings. If they differ then maybe it's where your problem is. Commented Oct 16, 2024 at 14:48
  • 1
    What happens when you step through your code with a debugger? Which variables have you inspected at which break points and what is the first statement that executes in a different way than expected while all the variables are still as they should be at that point? In short: have you performed a debugging session? Commented Oct 16, 2024 at 15:09
  • 1
    The loop in main does not fill in any of the prev_links. Commented Oct 16, 2024 at 15:40

1 Answer 1

0

It is useful to define a type to hold the head and tail pointers of the list since some functions may need to update both the head and tail pointers.

Fundamental operations include:

  • initializing the list
  • various ways to add an element to the list, such as:
    • prepending it to the start of the list
    • appending it to the end of the list
    • inserting it before some other element already on the list
    • (inserting it after some other element can be implemented by inserting it before the next element if it exists, or appending it to the list)
  • various ways to remove an element from the list, such as:
    • removing the first element
    • removing the last element
    • removing an element known to be on the list

Functions can be written to perform those operations, as in the following example based on OP's original code (OP's functions that that took a head pointer or a tail pointer have been changed to take a pointer to the list control structure):

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

typedef struct Node
{
    int value;
    struct Node *next_link;
    struct Node *prev_link;
} Node;

typedef struct List
{
    struct Node *head;
    struct Node *tail;
} List;

Node *create_node(int value)
{
    Node *new_node = malloc(sizeof(Node));
    new_node->value = value;
    new_node->next_link = NULL;
    new_node->prev_link = NULL;

    return new_node;
}

Node *node_next(Node *node)
{
    return node ? node->next_link : NULL;
}

Node *node_prev(Node *node)
{
    return node ? node->prev_link : NULL;
}

void free_node(Node *node)
{
    free(node);
}

void list_init(List *list)
{
    list->head = NULL;
    list->tail = NULL;
}

Node *list_first(List *list)
{
    return list->head;
}

Node *list_last(List *list)
{
    return list->tail;
}

/* Note: existingnode assumed to be on the list if non-null */
/* Note: if existingnode is null, newnode will be prepended to the list */
void list_insert_before(List *list, Node * restrict existingnode,
                        Node * restrict newnode)
{
    if (newnode)
    {
        Node *prev;

        if (existingnode == NULL)
        {
            /* newnode will be prepended before head (if it exists) */
            existingnode = list->head;
        }
        if (existingnode)
        {
            prev = existingnode->prev_link;
            existingnode->prev_link = newnode;
        }
        else
        {
            /* list is empty */
            prev = NULL;
            list->tail = newnode;
        }
        newnode->prev_link = prev;
        newnode->next_link = existingnode;
        if (prev)
        {
            prev->next_link = newnode;
        }
        else
        {
            /* newnode being prepended to the list */
            list->head = newnode;
        }
    }
}

void list_prepend(List *list, Node *node)
{
    /* Note: list->head may be null */
    list_insert_before(list, list->head, node);
}

void list_append(List *list, Node *node)
{
    if (node)
    {
        node->next_link = NULL;
        node->prev_link = list->tail;
        if (list->tail)
        {
            list->tail->next_link = node;
        }
        else
        {
            /* list is empty */
            list->head = node;
        }
        list->tail = node;
    }
}

/* Note: existingnode assumed to be on the list if non-null */
/* Note: if existingnode is null, newnode will be appended to the list */
void list_insert_after(List *list, Node * restrict existingnode,
                       Node * restrict newnode)
{
    if (existingnode == NULL || existingnode == list->tail)
    {
        list_append(list, newnode);
    }
    else
    {
        list_insert_before(list, existingnode->next_link, newnode);
    }
}

/* Note: node assumed to be on the list if non-null */
void list_remove_node(List *list, Node *node)
{
    if (node)
    {
        Node *next = node->next_link;
        Node *prev = node->prev_link;

        if (next)
        {
            next->prev_link = prev;
        }
        else
        {
            list->tail = prev;
        }
        if (prev)
        {
            prev->next_link = next;
        }
        else
        {
            list->head = next;
        }
        node->next_link = NULL;
        node->prev_link = NULL;
    }
}

Node *list_remove_first(List *list)
{
    Node *node = list_first(list);

    list_remove_node(list, node);
    return node;
}

Node *list_remove_last(List *list)
{
    Node *node = list_last(list);

    list_remove_node(list, node);
    return node;
}

void free_list_nodes(List *list)
{
    Node *temp;

    while ((temp = list_remove_first(list)) != NULL)
    {
        free_node(temp);
    }
}

void forward_traversing(List *list)
{
    Node *temp = list_first(list);

    while (temp != NULL)
    {
        printf("%d ", temp->value);
        temp = temp->next_link;
    }
    printf("\n");
}

void backward_traversing(List *list)
{
    Node *temp = list_last(list);

    while (temp != NULL)
    {
        printf("%d ", temp->value);
        temp = temp->prev_link;
    }
    printf("\n");
}

void show_first(List *list)
{
    Node *head = list_first(list);

    if (head)
    {
        printf("%d \n", head->value);
    }
    else
    {
        printf("(empty)\n");
    }
}

void show_last(List *list)
{
    Node *tail = list_last(list);

    if (tail)
    {
        printf("%d \n", tail->value);
    }
    else
    {
        printf("(empty)\n");
    }
}

int main()
{
    List list;
    Node *node;
    int i;

    list_init(&list);
    for (i = 10; i < 50; i += 10)
    {
        node = create_node(i);

        if (node)
        {
            list_append(&list, node);
        }
    }

    printf("Initial list\n");
    forward_traversing(&list);
    backward_traversing(&list);

    printf("Remove first node\n");
    node = list_remove_first(&list);    /* (10), 20, 30, 40 */
    forward_traversing(&list);
    backward_traversing(&list);

    printf("Prepend removed node to start of list\n");
    list_prepend(&list, node);          /* 10, 20, 30, 40 */
    forward_traversing(&list);
    backward_traversing(&list);

    printf("Remove last node\n");
    node = list_remove_last(&list);     /* 10, 20, 30, (40) */
    forward_traversing(&list);
    backward_traversing(&list);
    printf("Append removed node to end of list\n");
    list_append(&list, node);           /* 10, 20, 30, 40 */
    forward_traversing(&list);
    backward_traversing(&list);

    printf("Remove third node\n");
    node = node_next(node_next(list_first(&list))); /* (30) */
    list_remove_node(&list, node);      /* 10, 20, 40 */
    forward_traversing(&list);
    backward_traversing(&list);
    printf("Insert removed node after second node\n");
    list_insert_after(&list, node_next(list_first(&list)), node);
                                        /* 10, 20, 30, 40 */
    forward_traversing(&list);
    backward_traversing(&list);
    printf("Remove previous (third) node again\n");
    list_remove_node(&list, node);      /* 10, 20, 40 */
    forward_traversing(&list);
    backward_traversing(&list);
    printf("Insert removed node before third (original fourth) node\n");
    list_insert_before(&list, node_next(node_next(list_first(&list))),
                       node);           /* 10, 20, 30, 40 */
    forward_traversing(&list);
    backward_traversing(&list);

    printf("First node\n");
    show_first(&list);
    printf("Last node\n");
    show_last(&list);

    free_list_nodes(&list);
    return 0;
}

Output:

Initial list
10 20 30 40 
40 30 20 10 
Remove first node
20 30 40 
40 30 20 
Prepend removed node to start of list
10 20 30 40 
40 30 20 10 
Remove last node
10 20 30 
30 20 10 
Append removed node to end of list
10 20 30 40 
40 30 20 10 
Remove third node
10 20 40 
40 20 10 
Insert removed node after second node
10 20 30 40 
40 30 20 10 
Remove previous (third) node again
10 20 40 
40 20 10 
Insert removed node before third (original fourth) node
10 20 30 40 
40 30 20 10 
First node
10 
Last node
40 
Sign up to request clarification or add additional context in comments.

1 Comment

I'm not sure why the identifier list is getting specially highlighted in that code!

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.