# Detailed explanation of single linked list (the end of the text contains all the codes that have been completely tested ~ they can be taken by themselves if necessary)

Posted by lando on Tue, 02 Nov 2021 07:12:18 +0100

catalogue

Zero. Preface

1. Linked list and sequence list

1. Defects and advantages of sequence table

shortcoming

shortcoming

2. Logical and physical structure of linked list

1. Logical structure

2. Physical structure

3. Basic operation of single linked list

1. Define single linked list nodes

2. Create a single linked list node

4. Destroy the single linked list

4. Tail deletion and tail insertion

1. Tail plug

2. End deletion

6. Directional insertion

1. Insert before pos

2. Insert after pos

7. Directional deletion

1. Delete pos

2. Nodes after deleting pos

8. Find

9. All codes and test results

1.SList.h file

2.SList.c file

3.test.c file

4. Test results

10. Summary

# Zero. Preface

Single linked list plays a very important role in practical application, makes up for the shortage of sequential table, and has great advantages in space storage and memory occupation. This paper will introduce the basic operation of single linked list. At the end of the paper, there is a complete code that has been tested.

# 1. Linked list and sequence list

## 1. Defects and advantages of sequence table

The sequential table supports random access. Some algorithm structures need random access, such as binary search and optimized quick sorting. The random access here can only obtain data through the same subscript.

### shortcoming

1. The sequence table requires data to be stored in sequence, so when inserting or deleting data, a large amount of data needs to be moved, which is too expensive.

2. When the space is insufficient, the sequence table needs to be expanded. In order to avoid frequent expansion, it is usually expanded to twice the original capacity, but it is not known how much data needs to be stored during expansion, so it may cause a waste of space.

We designed the linked list according to the defects of the sequential list.

1. Apply for space on demand, release space without use, and there is no waste of space.

2. There is no need to move data during insertion and deletion.

### shortcoming

1. Every time a data is stored, a pointer to the next structure needs to be stored.

2. Random access is not supported.

# 2. Logical and physical structure of linked list

## 1. Logical structure

Logical structure is an abstract structure that is convenient for us to understand

On the left is the data field and on the right is the pointer field.

## 2. Physical structure

Physical structure is the structure actually stored in the computer

In addition to storing data, each structure also stores the address of the next structure.

# 3. Basic operation of single linked list

## 1. Define single linked list nodes

```typedef struct SListNode {
DataType data;
struct SListNode* next;
}SLTNode;```

A structure variable is defined as the node of the single linked list, including the value data and the pointer next to the next structure.

## 2. Create a single linked list node

```SLTNode* BuyListNode(DataType x)
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));//Make room for new nodes
assert(newnode);//Judge whether the returned pointer is null
newnode->data = x;
newnode->next = NULL;//Assign a value to the new node
return newnode;
}```

First, create a new node newnode and make room for it. Record its data value as x and the next value as NULL temporarily.

## 3. Print single linked list

```void print(SLTNode* phead)
{
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}//Traverse the entire linked list and stop printing when cur is empty
printf("NULL\n");
}```

Traverse from the beginning node until cur becomes empty, print all data values, and finally add NULL pointed to by the last node.

## 4. Destroy the single linked list

```void SListDestroy(SLTNode** pphead)
{
while (cur)
{
SLTNode* next = cur->next;
free(cur);//Free up cur space
cur = next;//Set cur as its next node
}
}```

Starting from the node, define a pointer cur that traverses the linked list. Each time cur = cur - > next, we need to define a next, because every time we release cur, we also need to release its next node, that is, cur - > next. If we don't need next to receive cur - > next in advance, we can't find its next element after cur is released.

When writing the code of single linked list, we should pay attention to a principle, that is, find the front and not the back, because the later can be modified by one or more next. When traversing with cur, we only need to finally set cur as the first element to change.

# 4. Tail deletion and tail insertion

## 1. Tail plug

```void SListPushBack(SLTNode** pphead, DataType x)
{
while (cur->next)
{
cur = cur->next;
}//Find the last node
cur->next = newnode;
}```

The premise of tail insertion is to find the tail node first. We still need to establish a cur traversing the linked list to find the last node, and then insert it. Note that we need to pass in the address of the pointer. Although we can modify the value of the linked list if only the pointer is passed, if there are no elements in the linked list, that is, phead=NULL, we need to set phead as a new node. At this time, direct assignment cannot be completed, so try to use secondary pointers for assignment.

## 2. End deletion

```void SListPopBack(SLTNode** pphead)
{
{
*pphead = NULL;//When there is only one node, the header pointer is assigned NULL
}
else
{
while (cur->next->next != NULL)
{
cur = cur->next;
}//Find the node that changes first, that is, the penultimate node, in order to assign its next value to NULL
free(cur->next);
cur->next = NULL;
}
}```

The idea of tail deletion is the same. First, find the last element through cur traversal, and then release it. Because the next of the last element is NULL, and we need to set the next pointing to the element to be empty after releasing the last element, so we need to get this element. When only one traversal node cur is used, We want cur to traverse to the penultimate node and modify its next pointer. So we use cur - > next to find the last node.

```void SListPushFront(SLTNode** pphead, DataType x)
{
*pphead = newnode;//Modify the header node, so you need to use the secondary pointer
}```

Create a new node, make its next point to the original head node, and then point the head node pointer to the new node.

```void SListPopFront(SLTNode** pphead)
{
*pphead = next;//As long as the header node changes, you need to use the secondary pointer
}```

First, you need to judge whether the linked list is empty. If it is empty, the program exits abnormally. If it is not empty, first save the next position of the header node with a pointer next, and then release the header node. When writing the linked list, you should also pay attention to saving the elements that have changed due to the change of an element and cannot be found after the change of the element.

# 6. Directional insertion

## 1. Insert before pos

```void SListInsertFront(SLTNode**pphead,SLTNode* pos, DataType x)
{
assert(pos);
{
SListPushFront(pphead, x);//Judge whether pos is the first element. If yes, it becomes header insertion
}
else
{
while (cur->next != pos)
{
cur = cur->next;
}
cur->next = newnode;
newnode->next = pos;//Insert newnode before pos
}
}```

Insert in front of the pos, adhering to the principle of looking before and not after. The previous element of the pos has also changed (- > next). Therefore, the final cur should point to the previous element of the pos, so that cur - > next points to the newly established node, and the next of the new node points to the pos.

## 2. Insert after pos

```void SListInsertBack(SLTNode** pphead,SLTNode* pos,DataType x)
{
assert(pos);//Judge whether pos is empty
newnode->next = pos->next;
pos->next = newnode;//Insert newnode after pos
}```

After the POS is inserted, the first change is the POS, and we have obtained the POS node, so we don't need to traverse. Just point the next of the POS to the newly established node, and the next of the newly established node to pos - > next.

# 7. Directional deletion

## 1. Delete pos

```void SListErase(SLTNode** pphead, SLTNode* pos)
{
assert(pos);//If pos does not exist, an error is reported
{
}
else
{
while (cur->next != pos)
{
cur = cur->next;
}
cur->next = pos->next;
free(pos);
}
}```

To delete POS, you also need to find the previous node of POS, that is, after traversal, set cur as the previous node of POS, make cur - > next = pos - > next, and then release the space of POS.

## 2. Nodes after deleting pos

```void SListEraseBack( SLTNode* pos)
{
assert(pos->next);//Judge whether the node after pos is legal
SLTNode* next = pos->next;//Record the next node of the node after the pos, which is convenient for assigning values to the next node of the pos
pos->next = next->next;
free(next);
}```

There is no need to traverse at this time, because the first changed node (POS) has been obtained. We can directly set pos - > next = pos - > next - > next, and then release pos - > next. Because the POS node has been deleted, we need to create a new next node to store pos - > next before that.

# 8. Find

```SLTNode* SListFind(SLTNode* pphead, DataType x)
{
while (cur)
{
if (cur->data == x)
{
return cur;//Find and return the node
}
cur = cur->next;
}
}```

Traverse all nodes, return the node if found, and return NULL if not found.

# 9. All codes and test results

## 1.SList.h file

```#define _CRT_SECURE_NO_WARNINGS 1
#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
#define DataType int
typedef struct SListNode {
DataType data;
struct SListNode* next;
}SLTNode;
void SListPushBack(SLTNode** pphead, DataType x);//Tail insertion
void SListInsertFront(SLTNode**pphead,SLTNode* pos, DataType x);//Fixed front insert
void SListInsertBack(SLTNode** pphead, SLTNode* pos, DataType x);//Fixed rear insert
void SListErase(SLTNode** pphead, SLTNode* pos);//Fixed point deletion
void SListEraseBack(SLTNode* pos);//Delete the next node after the fixed point

## 2.SList.c file

```#include "SList.h"
{
SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
assert(newnode);
newnode->data = x;
newnode->next = NULL;
return newnode;
}
{
while (cur != NULL)
{
printf("%d->", cur->data);
cur = cur->next;
}
printf("NULL\n");
}
{
while (cur)
{
SLTNode* next = cur->next;
free(cur);
cur = next;
}
}
{
while (cur->next)
{
cur = cur->next;
}
cur->next = newnode;
}
{
{
}
else
{
while (cur->next->next != NULL)
{
cur = cur->next;
}
free(cur->next);
cur->next = NULL;
}
}
{
}
{
}
{
assert(pos);
{
}
else
{
while (cur->next != pos)
{
cur = cur->next;
}
cur->next = newnode;
newnode->next = pos;
}
}
{
assert(pos);
newnode->next = pos->next;
pos->next = newnode;
}
{
assert(pos);
{
}
else
{
while (cur->next != pos)
{
cur = cur->next;
}
cur->next = pos->next;
free(pos);
}
}
void SListEraseBack( SLTNode* pos)
{
assert(pos->next);
SLTNode* next = pos->next;
pos->next = next->next;
free(next);
}
{
while (cur)
{
if (cur->data == x)
{
return cur;
}
cur = cur->next;
}
return NULL;
}```

## 3.test.c file

```#include"SList.h"
{
printf("****7.Fixed rear insert****8.Fixed delete\n");
}
int main()
{
int input = 0;
do {
scanf("%d", &input);
int x;
int y;
SLTNode* pos;
switch (input)
{
break;
case 2:scanf("%d", &x);
break;
break;
case 4:scanf("%d", &x);
break;
break;
case 6:scanf("%d", &x);
scanf("%d", &y);
break;
case 7:scanf("%d", &x);
scanf("%d", &y);
break;
case 8:scanf("%d", &x);
break;
case 9:
scanf("%d", &x);
if (pos == NULL)
{
printf("can't find!\n");
continue;
}
SListEraseBack(pos);
break;
break;
default:printf("wrong input!\n");
break;
}
} while (input);
return 0;
}```

## 4. Test results

1. Tail insertion: successful

2. Tail deletion: delete the tail until no error is reported. It is successful

4. Header deletion: delete the header until no error is reported. It is successful

5. Directional header insertion: insert header in front of the first element, insert header in front of other elements, and insert an error message at the position where there is no element. Success

6. Directional tail insertion: insert other elements and insert errors after no elements exist. Success is achieved

7. Fixed deletion: delete the linked list empty and report an error. The deletion is successful if no element is reported an error

8. Delete after fixing: delete and report an error after the last element, delete the non-existent element, delete the linked list and report an error. Success

9. Find: verified in the orientation, successful