Linear list - single linked list - array

Linear table

Sequential list and linked list

Abstract data structure - data combination and operation set

Header node: the first node that does not store data elements

First element node: the first node where data elements are stored

1, Definition of linear table

A finite sequence of zero or more data elements

There is order between elements. If there are multiple elements, the first element has no precursor and the last element has no successor. Every other element has and has only one precursor and one successor.

In a more complex linear table, a data element can be composed of several data items

2, Sequential storage structure of linear table

A storage unit with continuous addresses is used to store the data elements of the linear table in turn - physical address continuity

1. Generally, one-dimensional array is used to realize the sequential storage structure

//Maximum storage capacity
#define MAXSIZE 20
typedef struct Array
{
    int data[MAXSIZE];//An array stores data elements (or pointers) int* element
    int length;//Current length of linear table
    int Size;//Maximum capacity of linear meter
}Array
;
​

2. Three attributes are required to describe the sequential storage structure

Starting position of storage space: the storage position of array data is the storage position of storage space

Maximum storage capacity of linear table: array length MAXSIZE

Current length of linear table: length

Each storage unit in the memory has its own number, which is the address

3. Initialize linear table

//initialization
Array init_array()
{
    //Define an abstract data type
    Array array;
    array.length = 0;
    array.Size = MAXSIZE;
    return array;
}

4. Find elements

//Find element - returns the subscript of the element (you can also find according to the subscript and return the element value)
int find_ArrayElement(int find_key, Array* array)
{
    if (array->length == 0)
    {
        printf("Lookup error: the table is empty!\n");
        return -1;
    }
    for (int i = 0; i < array->length; i++)
    {
        if (array->data[i] == find_key)
        {
            return i;
        }
    }
    //Element not found
    return -1;
}
​
//Find by subscript
void find_ArrayIndex(int index,Array* array)
{
    //Judge whether the subscript is reasonable
    if(index<0||index>=array->length)
    {
        printf("Search error: subscript error!\n");
        return;
    }
    return array->data[index];
}

5. Insertion operation

Idea:

1. The insertion position is unreasonable and an exception is thrown

2. If the length of the linear table is greater than or equal to the length of the array, throw an exception or dynamically increase the capacity of the array

3. Traverse forward from the last element to the position to be inserted, and move them back one position respectively

4. Insert element, linear table length + 1

//Insert in two ways
​
1.
//Insert element - sequential insert
void insert_ArrayTail(int key, Array* array)
{
    //The array still has capacity to insert
    if (array->length < array->Size)
    {
        array->data[array->length] = key;
        array->length++;
    }
    else
    {
        printf("Insert error: insufficient array capacity!\n");
    }
}
​
2.
//Insert element - middle position insert
void insert_ArrayIndex(int key, int index, Array* array)
{
    //Determine whether the insertion position is correct
    if (index<0 || index>array->length)
    {
        printf("Insert error: insert position error!\n");
        return;
    }
    //Record the current array pointing position
    int pos = array->length;
    //The array still has capacity
    if (array->length < array->Size)
    {
        while (index<pos)
        {
            //Move backward one bit in turn
            array->data[pos] = array->data[pos - 1];
            pos--;
        }
        //Insert element
        array->data[index] = key;
        //Array length + 1
        array->length++;
    }
    else
    {
        printf("Insert error: insufficient array capacity!\n");
    }
}

6. Delete

Idea:

1. If the deletion position is unreasonable, an exception will be thrown

2. Traverse from the deletion position to the last element position and move them forward one position respectively

3. Table length-1

//Two ways
​
1.
//Delete element - delete according to the element
void delete_ArrayElement(int delete_key, Array* array)
{
    //Find the element subscript first
    int delete_index = find_Array(delete_key,array);
    //Judge whether the subscript is correct
    if (delete_index == -1)
    {
        printf("Delete error: this element is not in the array!\n");
        return;
    }
    //Move the elements forward in turn to overwrite the elements to be deleted
    while (delete_index < array->length)
    {
        //Element forward overlay
        array->data[delete_index] = array->data[delete_index + 1];
        delete_index++;
    }
    //Array element - 1
    array->length--;
}
​
2.
//Delete element - delete by subscript
void delete_ArrayIndex(int index, Array* array)
{
    //Judge whether the subscript is reasonable
    if (index<0 || index>=array->length)
    {
        printf("Error deleting subscript!\n");
        return;
    }
    //Move the elements forward in turn to overwrite the elements to be deleted
    while (index < array->length)
    {
        //Element forward overlay
        array->data[index] = array->data[index + 1];
        index++;
    }
    //Array element - 1
    array->length--;
​
}

7. Modification operation

//Two ways
1.
//Change element - change according to subscript
void change_ArrayIndex(int change_key,int index, Array* array)
{
    //Judge whether the subscript is reasonable
    if (index < 0 || index >= array->length)
    {
        printf("Change error: subscript error!\n");
        return;
    }
    array->data[index] = change_key;
}
​
2.     
//Change element - change according to the element
void change_ArrayElement(int key, int change_key, Array* array)
{
    //Find the element subscript first
    int change_pos = find_Array(key, array);
    //Judge whether the subscript is correct
    if (change_pos == -1)
    {
        printf("Change error: this element is not in the array!\n");
        return;
    }
    array->data[change_pos] = change_key;
}

8. Advantages and disadvantages

The sequential storage structure of linear table. When reading data (looking for elements - returning element values according to subscripts or changing elements), the time complexity is O(1), while when inserting and deleting, the time complexity is O(n).

Therefore, the sequential storage structure of linear table does not change much compared with the number of elements, but is more used to access data

advantage:

1. There is no need to add additional storage space to represent the logical relationship between elements

2. You can quickly access elements in any position in the table

Disadvantages:

1. Insert and delete operations require moving a large number of elements - time consuming

2. When the length of linear table changes greatly, it is difficult to determine the capacity of storage space

3. "Debris" causing storage space

3, Linked storage structure of linear list (single linked list)

1. Definitions

1. Features: use a group of arbitrary storage units to store the data elements of the linear table. This group of storage units can be continuous or discontinuous. Therefore, these data elements can exist in any location where memory is not occupied

In the chain structure, the storage address of its subsequent elements needs to be stored

2. The domain in which data element information is stored is called data field

3. The field storing the direct successor position is called pointer field

4. These two parts constitute the depositor image of the data element List, which is called the node

5.n nodes are linked into a linked list, which is the linked storage structure of linear list. Each node contains only one pointer field, so it is called single linked list

6. Initial node: the first node of the single linked list

7. Header pointer: the storage location of the first node of the linked list

8. Head node: a node attached before the first element node

2. Similarities and differences between head pointer and head node

Header pointer:

1. Pointer to the first node of the linked list. If the linked list has a head node, it refers to the pointer to the head node

2. The head pointer has the function of marking, so the head pointer is often labeled with the name of Lina watch

3. Whether the linked list is empty or not, the header pointer is not empty. The head pointer is a necessary element of the linked list (only through the head pointer can we find the subsequent nodes)

Header node:

1. It is set up for the unity and convenience of linked list operation. Before the first element, its data field is generally meaningless

2. With the header node, the operation of inserting and deleting the first element node before the first element node is unified with that of other nodes

3. The head node is not necessarily a necessary element of the linked list

3. Creation, addition, deletion, modification and query of single linked list

#include<stdio.h>
#include<stdlib.h>
#include<time.h>
​
​
//Define linked list nodes
typedef struct NodeList
{
    int element;//Data domain
    struct NodeList* pNext;//Pointer field
}Node;
​
//Initialize header node
Node* init_head();
​
//Insert element - value of random n elements - header interpolation
void allinit_List_head(int n, Node* node);
// Insert element - value of random n elements - tail interpolation
void allinit_List_tail(int n, Node* node);
//Insert element header method
void insert_ListHead(int key,Node* node);
//Insert element tail method
void insert_ListTail(int key, Node* node);
//Insert element - middle insert
void insert_ListIndex(int key,int index, Node* node);
//Delete element - delete according to the element
void delete_ListElement(int delete_key,Node* node);
//Delete element - delete according to the position of the element
void delete_ListIndex(int index, Node* node);
//Delete element - entire table delete
void delete_List(Node* node);
//Change element - change according to position
void change_List(int change_key, int index, Node* node);
//Find element - return the element position (define the initial node position as 1) (you can also return the node pointer)
int find_List(int find_key ,Node* node);
//Print linked list
void print(Node* node);
​
​
int main()
{
    //initialization
    Node* mylist = init_head();
    //Head insert
    insert_ListHead(2, mylist);
    //Tail insertion
    insert_ListTail(4, mylist);
    insert_ListHead(1, mylist);
    //Middle insertion
    insert_ListIndex(3, 3, mylist);
    //Whole table insert
    //allinit_List_head(0, mylist);
    delete_List(mylist);
    
    print(mylist);
​
​
    return 0;
}
​
//Initialize header node
Node* init_head()
{
    //Define a header node
    Node* head = (Node*)malloc(sizeof(Node));
    //Determine whether the initialization is successful
    if (head)//success
    {
        //Give a pointer to the pointer field in the header node
        head->pNext = NULL;
        //Indicates the number of linked list elements
        head->element = 0;
    }
    else//fail
    {
        printf("Failed to allocate memory!");
        exit(0);
    }
    return head;
}
​
//Insert element - the value of n random elements
void allinit_List_head(int n, Node* node)
{
    if (n < 1)
    {
        printf("Insert error: the number of elements cannot be less than 1!\n");
        return;
    }
    //Generate random number seed
    srand((unsigned int)time(NULL));
    for (int i = 0; i < n; i++)
    {
        //Initialize new node
        Node* temp = (Node*)malloc(sizeof(Node));
        //Assign a value to the data in the data field
        temp->element = rand() % 100 + 1;
​
        //Let this new node become the initial node
        temp->pNext = node->pNext;
        node->pNext = temp;
        //Linked list element + 1
        node->element++;
    }
​
}
​
// Insert element - value of random n elements - tail interpolation
void allinit_List_tail(int n, Node* node)
{
    if (n < 1)
    {
        printf("Insertion error: cannot be less than 1!\n");
        return;
    }
    //Generate random number seed
    srand((unsigned int)time(NULL));
    //Temporary pointer, used to traverse the linked list
    Node* pcurrent = node;
    //Traverse the linked list to the last node
    while (pcurrent->pNext)
    {
        pcurrent = pcurrent->pNext;
    }
    //Insert
    for (int i = 0; i < n; i++)
    {
        //Initialize new node
        Node* temp = (Node*)malloc(sizeof(Node));
        //Assign a value to the data in the data field
        temp->element = rand() % 100 + 1;
​
        //Let this new node become the last node
        pcurrent->pNext = temp;
        temp->pNext = NULL;
        //Move temporary pointer
        pcurrent = temp;
        //Linked list element + 1
        node->element++;
    }
}
​
//Insert element header method
void insert_ListHead(int key, Node* node)
{
    //Define a node to be inserted
    Node* temp = (Node*)malloc(sizeof(Node));
    //Insert element
    temp->element = key;
    //List head point
    temp->pNext = node->pNext;
    //The header node points to temp
    node->pNext = temp;
    //Number of linked list elements plus 1
    node->element++;
}
​
//Insert element tail method
void insert_ListTail(int key, Node* node)
{
    //Create node to be inserted
    Node* temp = (Node*)malloc(sizeof(Node));
    //Insert element
    temp->element = key;
    //Temporary pointer, used to traverse the linked list and find the insertion position (you can also define a tail node)
    Node* pcurrent = node;
    //Traversal linked list
    while (pcurrent->pNext)
    {
        pcurrent = pcurrent->pNext;
    }
    //At this time, pccurrent is the last node
    //Make it point to the node to be inserted
    pcurrent->pNext = temp;
    //Make temp the last node
    temp->pNext = NULL;
    //Number of linked list elements plus 1
    node->element++;
}
​
//Middle position insertion
void insert_ListIndex(int key,int index, Node* node)
{
    //Determine whether the insertion position is correct
    if (index<1 || index>node->element)
    {
        printf("Insert error: insert position error!\n");
        return;
    }
    //Define a node to be inserted
    Node* temp = (Node*)malloc(sizeof(Node));
    temp->element = key;
    //Record node location
    int pos = 1;
    //Find the location to insert
    //Temporary pointer, used to traverse the linked list
    Node* pcurrent = node;
    //Traversal linked list
    while (pcurrent->pNext)
    {
        //Find the subscript and insert it
        if (index == pos)
        {
            //Make the node to be inserted point to the original node
            temp->pNext = pcurrent->pNext;
            pcurrent->pNext = temp;
            //Linked list element + 1
            node->element++;
            return;
        }
        //Subscript not found
        pcurrent = pcurrent->pNext;
        pos++;
    }
​
}
​
//Delete element - delete according to the element
void delete_ListElement(int delete_key, Node* node)
{
    //The position of the element to be deleted first
    int delete_pos = find_List(delete_key, node);
    if (delete_pos == -1)
    {
        printf("Delete error: there is no such element!\n");
        return;
    }
    //Record the previous position of the element to be deleted
    int front_pos = 0;
    //Temporary pointer, used to traverse the linked list
    Node* pcurret = node;
    //Traversal linked list
    while (pcurret->pNext)
    {
        //Find node location
        if (front_pos == delete_pos - 1)
        {
            //Find the deleted node
            Node* free_node = pcurret->pNext;
            pcurret->pNext = pcurret->pNext->pNext;
            //Release deleted nodes
            free(free_node);
            //Linked list element-1
            node->element--;
            return;
        }
        //not found
        pcurret = pcurret->pNext;
        front_pos++;
    }
}
​
//Delete element - delete according to the position of the element
void delete_ListIndex(int index, Node* node)
{
    //Determine whether the element position is correct
    if (index<1 || index>node->element)
    {
        printf("Delete error: delete element position error!\n");
        return;
    }
    //Record the previous position of the element to be deleted
    int front_pos = 0;
    //Temporary pointer, used to traverse the linked list
    Node* pcurret = node;
    //Traversal linked list
    while (pcurret->pNext)
    {
        //Find node location
        if (front_pos == index - 1)
        {
            //Find the deleted node
            Node* free_node = pcurret->pNext;
            pcurret->pNext = pcurret->pNext->pNext;
            //Release deleted nodes
            free(free_node);
            //Linked list element-1
            node->element--;
            return;
        }
        //not found
        pcurret = pcurret->pNext;
        front_pos++;
    }
}
​
//Delete element - entire table delete
void delete_List(Node* node)
{
    //Define two temporary pointers. Pccurrent is used to move the pointer position, free_node is used to delete nodes
    Node* pcurrent = node->pNext;
    Node* free_node;
    while (pcurrent)
    {
        free_node = pcurrent;
        pcurrent = pcurrent->pNext;
        free(free_node);
        //The header pointer will not be deleted, element - 1
        node->element--;
    }
    //The header node pointer field is null
    node->pNext = NULL;
}
​
//Change element - change according to position
void change_List(int change_key, int index, Node* node)
{
    //Determine whether the position to be changed is correct
    if (index<1 || index>node->element)
    {
        printf("Change error: wrong position!\n");
        return;
    }
    //Record element location
    int change_pos = 1;
    //Temporary pointer, used to traverse the linked list
    Node* pcurrent = node;
    //Traversal linked list
    while (pcurrent->pNext)
    {
        //Find the position of the element to be changed
        if (change_pos == index)
        {
            pcurrent->pNext->element = change_key;
            return;
        }
        //not found
        pcurrent = pcurrent->pNext;
        change_pos++;
    }
}
​
//Find element - return the element position (define the initial node position as 1) (you can also return the node pointer)
int find_List(int find_key,Node* node)
{
    //Temporary pointer, used to traverse the linked list
    Node* pcurrent = node->pNext;
    //Represents the position of the element
    int pos = 1;
    //Traverse the linked list to find
    while (pcurrent)
    {
        if (pcurrent->element == find_key)
        {
            return pos;
        }
        pcurrent = pcurrent->pNext;
        //Move element position backward
        pos++;
    }
    return -1;
}
​
//Print linked list
void print(Node* node)
{
    //Temporary pointer, used to traverse the linked list
    Node* pcurrent = node;
    //Record element location
    int pos = 1;
    //Number of linked list elements
    printf("altogether %d Elements!\n", node->element);
    //Traverse the linked list and print
    while (pcurrent->pNext)
    {
        printf("The first %d The first element is:%d\n", pos, pcurrent->pNext->element);
        pcurrent = pcurrent->pNext;
        pos++;
    }
}
​

4, Selection of linear table

1. If the linear table needs frequent search and few insert and delete operations, the sequential storage structure should be adopted

2. If you need to insert and delete frequently, you should use the single linked list structure

3. When the number of elements in the linear table changes greatly or you don't know how big it is, it's best to use the single linked list structure. In this way, there is no need to consider the size of storage space

4. The sequential storage structure and chain storage structure of linear table have their own advantages and disadvantages. When using, the structure that can meet the requirements and has higher performance should be selected according to the actual situation

For example:

In game development, the user's personal information, in addition to inserting data during registration, is more often read data, and the sequential storage structure can be considered

For the player's weapon and equipment list, equipment will often be added or discarded. At this time, chain storage structure can be considered. However, this is only a simple metaphor, and the problems considered in reality will be more complex

5, Other chained storage structures

1. Static linked list: it is a method designed for high-level language without pointer to realize the ability of single linked list

2. Circular linked list: change the pointer field of the last node in the single linked list from null pointer to head node, so that the whole single linked list forms a closed loop

Solved: starting from a certain node, access to all nodes of the linked list

3. Bidirectional linked list: in the pointer field of each node of the single linked list, another pointer field pointing to its predecessor node is set (space for time)

0

Keywords: C Algorithm data structure linked list

Added by novicephp on Mon, 07 Feb 2022 07:15:36 +0200