[linked list of data structure] detailed graphics and texts teach you to play with the linked list

Time:2021-9-6

[recommended reading of series articles]

0. To the point

article[linked list of data structure] after reading this article, I finally understand the linked listThe chain storage structure has been introduced, and the most basic (simple) implementation of the chain storage structure – one-way linked list has been introduced.

One way linked list, as the name suggests, is one-way.

Because each node of the single linked list has only one data field and one pointer field, and the pointer field only stores the address of the next node, we can only find its direct successor node through a node, but we can’t find its direct predecessor node through a node.

In addition, since the single linked list ends at the tail node (the last node of the linked list), the pointer field of the tail node isNULL, to represent the termination of the linked list, which leads us to traverse to the tail node. If we want to traverse again, we can only manually return to the head node and start traversal.

In order to make up for the above two shortcomings of a single linked list, the following introduces two kinds of linked lists. They are all deformations of a single linked list. If you understand a single linked list, you will easily understand these two deformations.

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

1. One way circular linked list

1.1. Structure

The pointer field of the tail node of a single linked list isNULL, so the single linked list ends here. If we use the pointer field of the tail node of the single linked list to store the address of the head node, that is, the direct successor node of the tail node is the head node. In this way, the single linked list forms a ring (cycle), which is called single cycle linked list.

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

1.2. Implementation ideas

The one-way circular linked list evolved from the single linked list and is regarded as the “son” of the single linked list. Therefore, the structure of the single linked list is fully applicable to the one-way circular linked list. You can also see from the above figure that the structure has not changed greatly. The difference between the two is only in the tail node, so we only need to work on the tail node and the operations related to the tail node.

Therefore, the structure of one-way circular linked list is the same as that of single linked list.

/*The structure of the node of a one-way circular linked list*/
typedef struct _Node {
    int data; // Data fields: storing data
    struct _ Node *next; // Pointer field: stores the address of the direct successor node
} Node;

In order to unify the operation of empty linked list and non empty linked list, we use the linked list of the leading node to realize it.

1.3. Empty linked list and initialization

An empty linked list, as shown in the figure, has only one header pointer and header node:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

The pointer field of the head node points to itself to form a loop, which we can use to judge whether the linked list is empty.

if (head->next == head) {
    Printf ("empty linked list")\ n");
}

Want to initialize an empty linked list is very simple, create the head node, make the head nodenextThe pointer points to itself:

Node *create_node(int elem)
{
    Node *new = (Node *) malloc(sizeof(Node));
    new->data = elem;
    new->next = NULL;
    return new;
}

/**
 *Initialize linked list
 * p_ Head: pointer to the head pointer
 */
void init(Node **p_head)
{
    //Create header node
    Node *head_node = create_node(0);
    //The header pointer points to the header node
    *p_head = head_node;
    //The next pointer of the head node points to itself to form a ring
    head_node->next = head_node;
}

1.4. Insertion operation

Only head interpolation and tail interpolation are demonstrated here

[head insertion]

Because of the leading node, you do not need to consider whether it is an empty linked list. The following figure shows the process of inserting two elements into the head of an empty linked list:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

/**
 *The new node is the direct successor of the head node
 * p_ Head: pointer to the head pointer
 *Elem: data of new node
 */
void insert_at_head(Node **p_head, int elem)
{
    Node *new = create_node(elem);
    Node *head_ node = *p_ head; // Head node
    //After the new node is inserted into the head node
    new->next = head_node->next;
    head_node->next = new;
}

[tail interpolation]

In order to be as simple as possible, we do not set the tail pointer to the tail node. Therefore, before tail insertion, we need to traverse to the tail node with the help of a pointer, and then insert.

/**
 *Tail insertion method: the newly inserted node is always at the end of the linked list
 * p_ Head: pointer to the head pointer
 *Elem: data of new node
 */
void insert_at_tail(Node **p_head, int elem)
{
    Node *new = create_node(elem);
    Node *head_ node = *p_ head; // Head node
    Node *tail = head_ node; // The tail pointer points to the header node
    while (tail->next !=  head_ Node) {// tail traverses to the end of the linked list
        tail = tail->next;
    }
    //Tail insertion
    new->next = tail->next;
    tail->next = new;
}

1.5. Delete

The essence of deletion is to “skip” the node to be deleted, so we need to find the direct precursor node of the node to be deleted, and then make it the direct precursor nodenextThe pointer points to its direct successor node to “skip” the node to be deleted. Finally, save its data field and release the node to complete the deletion.

Only header deletion is demonstrated here.

Because the deleted node is the direct successor node of the head node, we don’t have to look for the direct precursor node of the node to be deleted.

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

/**
 *Header deletion method: delete the node after the header node
 * p_ Head: pointer to the head pointer
 *Elem: pointer to save data variable
 */
void delete_from_head(Node **p_head, int *elem)
{
    Node *head_ node = *p_ head; // Head node
    if (head_node->next == head_node) {
        Printf ("empty linked list, no element can be deleted\ n");
        return;
    }
    Node *first_ node = head_ node->next; // First node: the next node of the first node
    *elem = first_ node->data; // Save the data of the deleted node
    head_ node->next = first_ node->next; // Delete Vertex 
    free(first_ node); // release
}

1.6. Traversal operation

We can cycle through the linked list again and again. The following is the code for cyclic printing of nodes 20 times:

/**
 *Cycle printing 20 nodes
 */
void output_20(Node *head)
{
    if (head->next == head) {
        Printf ("empty linked list")\ n");
        return;
    }
    Node *p = head->next;
    for (int i = 0; i <= 20; i++) {
        if (p !=  Head) {// do not print header nodes
            printf("%d ", p->data);
        }
        p = p->next;
    }
    printf("\n");
}

2. Two way linked list

2.1. Structure

As the name suggests, a two-way linked list has two directions, one pointing forward and the other pointing back. In this way, we make up for the defect that a node of the single linked list can only find its direct successor. As shown in the figure:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

2.2. Implementation ideas

In order to achieve the effects before and after the signifier, onlynextPointers are definitely not enough, so we need to add another pointer——prev, the pointer points to the direct precursor node of a node.

/*Node structure of bidirectional linked list*/
typedef struct _Node {
    int data; // Data domain
    struct _ Node *prev; // Pointer to the direct precursor node
    struct _ Node *next; // Pointer to direct successor node
} Node;

2.3. Empty linked list and initialization

The empty linked list of the two-way linked list is shown in the figure:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

To initialize such an empty linked list, you need to create a header node, and then empty the two pointer fields:

Node *create_node(int elem)
{
    Node *new = (Node *)malloc(sizeof(Node));
    new->data = elem;
    new->prev = NULL;
    new->next = NULL;
    return new;
}

void init(Node **p_head)
{
    //Create header node
    Node *head_node = create_node(0);
    //The header pointer points to the header node
    *p_head = head_node;
}

2.4. Insertion operation

Only the head insertion method is demonstrated here. The process is as follows:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

The code is as follows:

/**
 *The new node is the direct successor of the head node
 * p_ Head: pointer to the head pointer
 *Elem: data of new node
 */
void insert_at_head(Node **p_head, int elem)
{
    Node *new = create_node(elem);
    Node *head_ node = *p_ head; // Head node
    if (head_ node->next !=  Null) {// not an empty linked list
        Node *first_ node = head_ node->next; // First node: the next node of the first node
        //The prev pointer of the first node points to the new node
        first_node->prev = new;
        //The next pointer of the new node points to the first node
        new->next = first_node;
    }
    //The prev pointer of the new node points to the header node
    new->prev = head_node;
    //The next pointer of the header node points to the new node
    head_node->next = new;
}

2.5. Delete

Only header deletion is demonstrated here. The following figure shows the process of deleting a two-way linked list header with two element nodes into an empty linked list:

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

The code is as follows:

/**
 *Head deletion
 * p_ Head: pointer to the head pointer
 *Elem: pointer to save variable
 */
void delete_from_head(Node **p_head, int *elem)
{
    Node *head_ node = *p_ head; // Head node
    Node *first_ node = head_ node->next; // First node to be deleted: the next node of the head node
    if (head_ Node - > next = = null) {// null
        Printf ("empty linked list, no element can be deleted\ n");
        return;
    }
    *elem = first_ node->data; // Save data
    
    if (first_node->next != NULL) {
        first_node->next->prev = first_node->prev;
    }
    first_node->prev->next = first_node->next;
    free(first_node);
}

2.6. Traversal operation

YesnextPointer field, we can traverse backward all the way; YesprevPointer field, we can traverse all the way forward.

The code is no longer shown here.

3. Summary

Knowing the one-way circular linked list and two-way linked list is like taking building blocks. We can also create a two-way circular linked list. There is no more demonstration here. Readers can try it by themselves. As long as you understand the above three linked lists, it is not difficult.

The above is part of the tricks of the linked list, which will continue to be updated in the future.

Complete code, please move toGitHub | Giteeobtain.

Please correct any errors.

If you think it’s good, you can praise and pay attention. There will be more articles on data structures and algorithms in the future.

[linked list of data structure] detailed graphics and texts teach you to play with the linked list

Recommended Today

SQL exercise 20 – Modeling & Reporting

This blog is used to review and sort out the common topic modeling architecture, analysis oriented architecture and integration topic reports in data warehouse. I have uploaded these reports to GitHub. If you are interested, you can have a lookAddress:https://github.com/nino-laiqiu/TiTanI recorded a relatively complete development process in my hexo blog deployed on GitHub. You can […]