Linear discrete storage linked list in data structure

Posted by JustinMs66 on Tue, 25 Jan 2022 15:39:16 +0100

In the previous section, we have learned about continuous storage in linear storage. We also call this storage structure sequential table or array. We also know that linear continuous storage has the following advantages and disadvantages:

  • Advantages: it can quickly add and access elements
  • Disadvantages: inserting or deleting elements will move a large number of original elements

In this section, we will learn about another linear data structure studied in data structure - discrete storage. We can also call linear discrete storage linked list. The basic structure of the linked list is shown in the following figure:

If you haven't read the previous departmental articles in this series, it is recommended that you read the previous contents through the following links:

1, Implementation process of linked list

1. Define linked list nodes

Compared with sequential list, the storage structure of linked list does not need to move a large number of elements when inserting and deleting. However, it is not easy to realize the operation of the ith element in the random access element linear table. Therefore, the linked list is applicable to linear tables that need frequent insertion and deletion operations, such as aircraft flight passenger table.

First, we define a 02 linklist Cpp file needs to introduce the basic c language header file and define the structure of linked list nodes

# include <stdio. h> / / standard io header, including printf function
# include <malloc. h> / / contains malloc functions. On mac computers, change to sys / malloc h
# include <stdlib. h> / / including exit function

typedef struct Node
{
    int data;           // Data domain
    struct Node *pNext; // Pointer field
} NODE, *PNODE;         // Node is equivalent to struct Node, *PNODE is equivalent to * Node

2. Create linked list

Next, we define the function to create the linked list

PNODE create_list(void)
{
    int len; // Effective number of storage nodes
    int val; //Store the value of the temporarily stored node entered by the user

    // Assign a header node that does not have any data
    PNODE pHead = (PNODE)malloc(sizeof(NODE));
    if (NULL == pHead)
    {
        printf("memory allocation failed!\n");
        exit(-1);
    }

    // In the initial state, the tail node and the head node of the linked list point to the same memory (that is, the head node is the tail node), and the pointer field is NULL
    PNODE pTail = pHead;
    pTail->pNext = NULL;

    printf("Please enter the number of linked list nodes you need to generate: len=");
    scanf("%d", &len);

    for (int i = 0; i < len; i++)
    {
        printf("Please enter page%d Values of nodes", i + 1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if (NULL == pNew)
        {
            printf("Allocation failed, program terminated!\n");
            exit(-1);
        }

        // Assign a value to the new node after the assignment is successful
        pNew->data = val;
        // Let the pointer field point to the latest node at the end of the linked list to add new nodes
        pTail->pNext = pNew;
        // The pointer field of the new node is NULL
        pNew->pNext = NULL;

        // Finally, let the tail node point to the new node.
        pTail = pNew;
    }

    // After the linked list is created, return to the header node
    return pHead;
}

3. Traverse linked list elements

Starting from the head node, if the pointer field of the linked list node is not NULL, the data is output

void traverse_list(PNODE pHead)
{
    // Assign the first node to the variable p
    PNODE p = pHead->pNext;

    while (NULL != p)
    {
        // If p is not NULL, it means there is data, then the data of p will be output
        printf("%d  ", p->data);
        // After outputting the data field of p, let p point to the next node
        p = p->pNext;
    }
    printf("\n");
    return;
}

4. Judge whether the linked list is empty and calculate the length of the linked list

If the pointer field of the chain header node is empty, the linked list is empty. The length is calculated by traversing the linked list, as shown in the following code

// Determine whether the linked list is empty
bool is_empty(PNODE pHead)
{
    if (NULL == pHead->pNext)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// Calculate the length of the linked list
int length_list(PNODE pHead)
{
    PNODE p = pHead->pNext;
    int len = 0;
    while (NULL != 0)
    {
        ++len;
        p = p->pNext;
    }
    return len;
}

5. Linked list sorting

Next, we sort the linked list nodes according to the data field values from small to large. The sorting of the linked list is similar to that of the sequential list. We use two node variables to temporarily store the two nodes in the comparison, as shown in the following code

// Linked list sorting
void sort_list(PNODE pHead)
{
    int i, j, t;
    int len = length_list(pHead);
    // Two node variables, p and q, are defined to temporarily store exchange nodes
    PNODE p, q;

    // Let p point to the current node
    for (i = 0, p = pHead->pNext; i < len; i++, p = p->pNext)
    {
        // Let q point to the next node
        for (j = i + 1, q = p->pNext; i < len; j++, q = q->pNext)
        {
            // Compare the current node with the next node. If the data field of the current node is larger than that of the next node, the data will be exchanged
            if (p->data > q->data)
            {
                t = p->data;
                p->data = q->data;
                q->data = t;
            }
        }
    }
}

6. Insert new node

In the next insert and delete operations, we remember that the index of the linked list is position, and position starts from 0. First, insert a node in the position position position of the linked list. The value of the node is val, and the code is as follows

// Insert node
bool insert_list(PNODE pHead, int position, int val)
{
    int len = length_list(pHead);
    if (len < 0 || position > len)
    {
        return false;
    }

    int i = 0;
    PNODE p = pHead;
    // Use the while loop to make the p variable point to the previous node of the position node
    while (NULL != p->pNext && i < position)
    {
        p = p->pNext;
        ++i;
    }

    // When the program is executed here, p has pointed to the previous node of the position node. It doesn't matter whether the position node is empty or not

    // Insertion procedure 1: assign a new node
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    if (NULL == pNew)
    {
        printf("Dynamic memory allocation failed");
        exit(-1);
    }
    // Insertion process 2: assign the incoming value to the data field of the new node
    pNew->data = val;

    // Insertion procedure 3: use the variable q to temporarily store the position node
    PNODE q = p->pNext;
    // Insertion process 4: point the previous node of the position node to the new node
    p->pNext = pNew;
    // Insertion process 5: point the new node to the position node
    pNew->pNext = q;

    return true;
}

7. Delete node

Deleting a node is similar to inserting a node. The difference is that after finding the position node, the insert node dynamically allocates new space and inserts it into the position position of the original linked list. After finding the position node, the delete node releases the space of the position node, and then connects the two unconnected nodes next to the original position.

// Delete node
bool delete_list(PNODE pHead, int position, int *pVal)
{
    int len = length_list(pHead);
    if (len < 0 || position > len)
    {
        return false;
    }

    int i = 0;
    PNODE p = pHead;

    // Use the while loop to make the p variable point to the previous node of the position node
    while (NULL != p->pNext && i < position)
    {
        p = p->pNext;
        ++i;
    }

    // Returns false if the position node is NULL
    if (NULL == p->pNext)
    {
        return false;
    }

    // When the program is executed here, p has pointed to the previous node of the position node, and the position node exists
    // Delete procedure 1 and let the q variable point to the position node
    PNODE q = p->pNext;
    // Delete process 2 and assign the data of the position node to pVal
    *pVal = q->data;

    // Delete process 3 so that the previous node of the position node points to the next node of the position node
    p->pNext = p->pNext->pNext;

    // Delete process 4, release the memory pointed to by the position node and point the q variable to NULL
    free(q);
    q = NULL;

    return true;
}

2, Testing and verification

1. Test

All test codes are as follows

#include <stdio.h>
#include <sys/malloc.h>
#include <stdlib.h>

// Define linked list nodes
typedef struct Node
{
    int data;           // Data domain
    struct Node *pNext; // Pointer field
} NODE, *PNODE;         // Node is equivalent to struct Node, *PNODE is equivalent to * Node

// Create an acyclic single linked list
PNODE create_list(void)
{
    int len; // Effective number of storage nodes
    int val; //Store the value of the temporarily stored node entered by the user

    // Assign a header node that does not have any data
    PNODE pHead = (PNODE)malloc(sizeof(NODE));
    if (NULL == pHead)
    {
        printf("memory allocation failed!\n");
        exit(-1);
    }

    // In the initial state, the tail node and the head node of the linked list point to the same memory (that is, the head node is the tail node), and the pointer field is NULL
    PNODE pTail = pHead;
    pTail->pNext = NULL;

    printf("Please enter the number of linked list nodes you need to generate: len=");
    scanf("%d", &len);

    for (int i = 0; i < len; i++)
    {
        printf("Please enter page%d Values of nodes:", i + 1);
        scanf("%d", &val);

        PNODE pNew = (PNODE)malloc(sizeof(NODE));
        if (NULL == pNew)
        {
            printf("Allocation failed, program terminated!\n");
            exit(-1);
        }

        // Assign a value to the new node after the assignment is successful
        pNew->data = val;
        // Let the pointer field point at the end of the linked list point to the latest node to add a new node
        pTail->pNext = pNew;
        // The pointer field of the new node is NULL
        pNew->pNext = NULL;

        // Finally, let the tail node point to the new node.
        pTail = pNew;
    }

    // After the linked list is created, the header node is returned
    return pHead;
}

// Traversal linked list
void traverse_list(PNODE pHead)
{
    // Assign the first node to the variable p
    PNODE p = pHead->pNext;

    while (NULL != p)
    {
        // If p is not NULL, it means there is data, then the data of p is output
        printf("%d  ", p->data);
        // After outputting the data field of p, let p point to the next node
        p = p->pNext;
    }
    printf("\n");
    return;
}

// Determine whether the linked list is empty
bool is_empty(PNODE pHead)
{
    if (NULL == pHead->pNext)
    {
        return true;
    }
    else
    {
        return false;
    }
}

// Calculate the length of the linked list
int length_list(PNODE pHead)
{
    PNODE p = pHead->pNext;
    int len = 0;
    while (NULL != p)
    {
        ++len;
        p = p->pNext;
    }
    return len;
}

// Linked list sorting
void sort_list(PNODE pHead)
{
    int i, j, t;
    int len = length_list(pHead);
    // Two node variables, p and q, are defined to temporarily store exchange nodes
    PNODE p, q;

    // Let p point to the current node
    for (i = 0, p = pHead->pNext; i < len - 1; i++, p = p->pNext)
    {
        // Let q point to the next node of the current node
        for (j = i + 1, q = p->pNext; j < len; j++, q = q->pNext)
        {
            // Compare the current node with the next node. If the data field of the current node is larger than that of the next node, the data will be exchanged
            if (p->data > q->data)
            {
                t = p->data;
                p->data = q->data;
                q->data = t;
            }
        }
    }
}

// Insert node
bool insert_list(PNODE pHead, int position, int val)
{
    int len = length_list(pHead);
    if (len < 0 || position > len)
    {
        return false;
    }

    int i = 0;
    PNODE p = pHead;
    // Use the while loop to make the p variable point to the previous node of the position node
    while (NULL != p->pNext && i < position)
    {
        p = p->pNext;
        ++i;
    }

    // When the program is executed here, p has pointed to the previous node of the position node. It doesn't matter whether the position node is empty or not

    // Insertion procedure 1: assign a new node
    PNODE pNew = (PNODE)malloc(sizeof(NODE));
    if (NULL == pNew)
    {
        printf("Dynamic memory allocation failed");
        exit(-1);
    }
    // Insertion process 2: assign the incoming value to the data field of the new node
    pNew->data = val;

    // Insertion procedure 3: use the variable q to temporarily store the position node
    PNODE q = p->pNext;
    // Insertion process 4: point the previous node of the position node to the new node
    p->pNext = pNew;
    // Insertion process 5: point the new node to the position node
    pNew->pNext = q;

    return true;
}

// Delete node
bool delete_list(PNODE pHead, int position, int *pVal)
{
    int len = length_list(pHead);
    if (len < 0 || position > len)
    {
        return false;
    }

    int i = 0;
    PNODE p = pHead;

    // Use the while loop to make the p variable point to the previous node of the position node
    while (NULL != p->pNext && i < position)
    {
        p = p->pNext;
        ++i;
    }

    // Returns false if the position node is NULL
    if (NULL == p->pNext)
    {
        return false;
    }

    // When the program is executed here, p has pointed to the previous node of the position node, and the position node exists
    // Delete procedure 1 and let the q variable point to the position node
    PNODE q = p->pNext;
    // Delete process 2 and assign the data of the position node to pVal
    *pVal = q->data;

    // Delete process 3 so that the previous node of the position node points to the next node of the position node
    p->pNext = p->pNext->pNext;

    // Delete process 4, release the memory pointed to by the position node and point the q variable to NULL
    free(q);
    q = NULL;

    return true;
}

int main()
{
    // Create a linked list, define the length as 6, and enter 1, 5, 6, 4, 3 and 2
    PNODE pHead = create_list();

    // Traversal elements: output 1 5 6 4 3 2
    traverse_list(pHead);

    // Linked list sorting
    sort_list(pHead);
    // Traversal elements: output 1 2 3 4 5 6
    traverse_list(pHead);

    // Add element 7 at index 0
    insert_list(pHead, 0, 7);
    // Traversal elements: output 7 1 2 3 4 5 6
    traverse_list(pHead);

    // Delete the element at index 5 and output the deleted element
    int val;
    delete_list(pHead, 5, &val);
    // Traversal element, output:
    traverse_list(pHead);
    // Print deleted elements
    printf("The deleted element data field is%d\n", val);

    return 0;
}

2. Results

The results of program compilation and execution are as follows:

pan@pandeMBP ds % g++ 02-LinkList.cpp
pan@pandeMBP ds % ./a.out 
Please enter the number of linked list nodes you need to generate: len=6
 Please enter the value of the 1st node:1
 Please enter the value of the second node:5
 Please enter the value of the 3rd node:6
 Please enter the value of the 4th node:4
 Please enter the value of the 5th node:3
 Please enter the value of the 6th node:2
1  5  6  4  3  2  
1  2  3  4  5  6  
7  1  2  3  4  5  6  
7  1  2  3  4  6  
The deleted element data field is 5

This article is originally launched from wx subscription number: geek development up, reprint is prohibited

Topics: C C++ Algorithm data structure linked list