【Data Structure & Algorithm】Analysis of Linked List Characteristics

1. The underlying storage structure

  • The array needs a contiguous memory space for storage, and the requirements for memory are relatively high. If we apply for a 100MB array, when there is no contiguous and large enough storage space in the memory, even if the remaining total available space in the memory is greater than 100MB, the application will still fail.
  • The linked list is just the opposite. It does not need a continuous memory space. It uses a "pointer" to connect a group of scattered memory blocks in series, so if we apply for a 100MB linked list, there will be no problem at all.

2. Linked list classification

2.1 Single linked list

String all the nodes together. In addition to storing data, each node of the linked list also needs to record the address of the next node on the chain. As shown in the figure, we call this pointer that records the address of the next node as the successor pointer next.
Insert picture description here

  • Head node & tail node

    • We habitually call the first node the head node and the last node as the tail node.

    • The head node is used to record the base address of the linked list. With it, we can traverse the entire linked list

    • The special point of the end node is: the pointer does not point to the next node, but to an empty address NULL, which means this is the last node on the linked list

  • Sentinel node: For convenience of operation, sometimes the head node is set to a node that stores data as null

2.2 Circular linked list

Circular linked list is a special kind of singly linked list. In fact, the circular linked list is also very simple. The only difference between it and a singly linked list is the end node .

  • The pointer of the end node of the singly linked list points to an empty address, indicating that this is the last node.
  • The pointer of the end node of the circular linked list points to the head node of the linked list. It is connected end to end like a ring, so it is called a "circular" linked list
    Insert picture description here

2.3 doubly linked list

The doubly linked list requires two additional spaces to store the addresses of the successor node and the predecessor node. Therefore, if you store the same amount of data, a doubly linked list will take up more memory space than a singly linked list. Although two pointers waste storage space, they can support two-way traversal, which also brings flexibility in doubly linked list operations.

From a structural point of view, a doubly linked list can support O(1) time complexity to find the precursor node. It is this feature that makes the insertion and deletion of a doubly linked list in some cases better than a singly linked list. Simple and efficient .
Insert picture description here

2.4 Two-way circular linked list

Insert picture description here

3. Operation time complexity analysis

3.1 Insert & delete (theory)

  • When inserting and deleting arrays, in order to maintain the continuity of memory data, a large amount of data needs to be moved, so the time complexity is O(n)
  • To insert or delete a piece of data in the linked list, we do not need to move the nodes in order to maintain the continuity of the memory, because the storage space of the linked list itself is not continuous. Therefore, it is very fast to insert and delete a piece of data in the linked list. We only need to consider the pointer changes of adjacent nodes, so the corresponding time complexity is O(1)

3.2 Insert & Delete (actual)

Insertion and deletion actually have the following two situations:

  • Delete the node of "a given value" == Insert the node after the given value
    • Regardless of whether it is a singly linked list or a doubly linked list, in order to find a node with a value equal to a given value, you need to traverse the comparison one by one from the beginning node until you find a node with a value equal to the given value, and then go through what I said earlier Pointer operation deletes it.
    • Although the time complexity of the simple deletion operation is O(1), the time of traversal search is the main time-consuming point, and the corresponding time complexity is O(n). According to the addition rule in the time complexity analysis, the total time complexity of the linked list operation corresponding to the node whose value is equal to the given value is O(n)
  • Delete the node pointed by the given pointer, that is, delete the node that has been given == After inserting the given node
    • Singly linked list: we have found the node to be deleted, but to delete a certain node q, we need to know its predecessor node, and singly linked list does not support direct access to the predecessor node, so in order to find the predecessor node, we still have to Traverse the linked list from the beginning node until p->next=q, indicating that p is the predecessor node of q. Therefore, the singly linked list deletion operation requires O(n) time complexity
    • Doubly linked list: Because the nodes in the doubly linked list have saved the pointers of the predecessor nodes, there is no need to traverse like a singly linked list. Therefore, the doubly linked list only needs to be completed within O(1) time complexity

3.3 Random access

  • If the linked list wants to randomly access the k-th element, it is not as efficient as an array (according to the first address and subscript, the corresponding memory address can be directly calculated by the addressing formula)
  • The data in the linked list is not stored continuously, and it needs to be traversed one by one according to the pointer until the corresponding node is found.
    • Singly linked list: traverse from beginning to end
    • Doubly linked list: we can record the last searched position p, each time we query, according to the size relationship between the value to be searched and p, we decide whether to search forward or backward, so we only need to search half of the data on average

4. Linked List VS Array

4.1 Operation time complexity

Array Linked list
Insert delete O (n) O (1)
Random access O (1) O (n)

4.2 cpu cache read ahead

  • The array is simple and easy to use. It uses continuous memory space in implementation. You can use the cache mechanism of the CPU to pre-read the data in the group, so the access efficiency is higher.
  • The linked list is not stored continuously in the memory, so it is not friendly to the CPU cache, and there is no way to effectively pre-read

4.3 Dynamic Expansion (Key Points)

  • The disadvantage of the array is that it has a fixed size, and once declared, it will occupy the entire contiguous memory space.
    • If the declared array is too large, the system may not have enough contiguous memory space allocated to it, resulting in "out of memory"
    • If the declared array is too small, it may be insufficient. At this time, you can only apply for a larger memory space and copy the original array into it, which is very time-consuming
    • Although the bottom layer of ArrayList implements dynamic expansion, assuming that ArrayList stores 1GB of data, there is no free space at this time. When we insert data again, ArrayList will apply for a 1.5GB storage space and change the original size. 1GB of data is copied to the newly requested space
  • The linked list itself has no size limit and naturally supports dynamic expansion. I think this is also the biggest difference between it and an array

4.4 Memory utilization

  • In general, the linked list can be dynamically expanded, so the memory utilization rate is higher than that of the general array. But if the array is initialized when the number of elements to be stored is known, the memory is rarely wasted, and the array is better
  • Linked lists are not suitable for scenarios with strict memory requirements
    • Each node in the linked list needs to consume additional storage space to store a pointer to the next node, so the memory consumption will double. But for larger Nodes, this point of memory for storing pointers can be ignored
    • Frequent insertion and deletion operations on the linked list will also lead to frequent memory applications and releases, which is easy to cause memory fragmentation. If it is Java language, it may cause frequent GC (Garbage Collection)

Guess you like

Origin blog.csdn.net/weixin_43935927/article/details/108710424