Structure and Algorithm (03): singly linked list and doubly linked list

Source code of this article: GitHub·click here || GitEE·click here

1. Introduction to Linked List

1. The concept of linked list

A linked list is a non-contiguous, non-sequential storage structure on a physical storage unit, and the logical order of data elements is realized by the link order of pointers in the linked list. The linked list consists of a series of nodes, which can be dynamically generated at runtime. The node includes two parts: one is the data field for storing data elements, and the other is the pointer field for storing the address of the next node.

2. Basic features

Memory storage

Logical structure

Characteristic description

  • Physical storage is disordered and discontinuous;
  • The linked list is composed of multiple nodes in a chain structure;
  • On the logical level, an orderly link structure is formed;

The linked list structure solves the defect that the number of elements in the array storage needs to be known in advance, and can make full use of the memory space and realize flexible dynamic memory management.

Two, singly linked list

1. Basic description

A singly linked list is a kind of linked list. Its characteristic is that the link direction of the linked list is one-way. The traversal of the linked list should be read sequentially from the head; the node is composed, and the head pointer points to the first node to become the head of the table, and terminates At the last pointer to NULL.

2. Basic operations

adding data

  • Initialize the head node as the head of the linked list;
  • Modify the next pointer of the current end node;
  • The newly added node house is at the end of the linked list;

delete data

Traverse to find the node to be deleted, and point the pointer of the previous node of the deleted node to the next node of the deleted node;

Three, doubly linked list

1. Concept description

A doubly linked list is also called a double-linked list, which is a kind of linked list. Each data node in the linked list has two pointers, which point to the direct successor and the direct predecessor. Starting from any node in the doubly linked list, it can be very fast To access its predecessor and successor nodes, most of the use of the linked list structure is to construct a two-way circular linked list.

2. Basic operations

adding data

  • Traverse to find the last node of the linked list;
  • Modify the next pointer of the current end node;
  • The newly added node house is at the end of the linked list;
  • Add the prev pointer of the latest tail node;

delete data

  • Doubly linked list, based on the operation to delete the node;
  • Operate the Node2 node to be deleted in the above figure;
  • Node2.prev.next = Node2.next;
  • Node2.next.prev = Node2.prev;

Through the operation of the above process, a node in the linked list is deleted, and the remaining nodes are connected into a chain structure again.

3. Source code analysis

In the Java API, LinkedList is a typical doubly linked list structure. The following is based on the LinkedList source code to see the operation of the doubly linked list.

Base case

public class M01_Linked {
    
    
    public static void main(String[] args) {
    
    
        List<User> userList = new LinkedList<>() ;
        User removeUser = new User(200,"Second") ;
        // 添加元素
        userList.add(new User(100,"First")) ;
        userList.add(removeUser) ;
        userList.add(new User(300,"Third")) ;
        System.out.println("初始化:"+userList);
        // 修改元素
        userList.get(0).setUserName("Zero");
        System.out.println("修改后:"+userList);
        // 删除元素
        userList.remove(removeUser) ;
        System.out.println("删除后:"+userList);
    }
}
class User {
    
    
    private Integer userId ;
    private String userName ;
    public User(Integer userId, String userName) {
    
    
        this.userId = userId;
        this.userName = userName;
    }
    @Override
    public String toString() {
    
    
        return "User{" +
                "userId=" + userId +
                ", userName='" + userName + '\'' +
                '}';
    }
    // 省略Get和Set方法
}

Node description

Three core descriptions of nodes: data, next pointer, prev pointer.

private static class Node<E> {
    
    
    E item;         // 数据
    Node<E> next;   // 下个指针
    Node<E> prev;   // 上个指针
    Node(Node<E> prev, E element, Node<E> next) {
    
    
        this.item = element;
        this.next = next;
        this.prev = prev;
    }
}

First node processing

Based on the LinkedList source code, the head-to-end node method, and the first pointer characteristic of the double-linked list in the above figure, the source code is well understood here.

public class LinkedList {
    
    
    transient Node<E> first;
    transient Node<E> last;
    // 处理首节点
    private void linkFirst(E e) {
    
    
        final Node<E> f = first;
        final Node<E> newNode = new Node<>(null, e, f);
        first = newNode;
        if (f == null)
            last = newNode;
        else
            f.prev = newNode;
    }
    // 处理尾节点
    void linkLast(E e) {
    
    
        final Node<E> l = last;
        final Node<E> newNode = new Node<>(l, e, null);
        last = newNode;
        if (l == null)
            first = newNode;
        else
            l.next = newNode;
    }
}

Add node

The method of adding a node directly calls the linkLast method and puts the new node at the end of the linked list.

public boolean add(E e) {
    
    
    linkLast(e);
    return true;
}

Delete node

Step 1: Traverse the comparison and find the node to be deleted;

public boolean remove(Object o) {
    
    
    if (o == null) {
    
    
        for (Node<E> x = first; x != null; x = x.next) {
    
    
            if (x.item == null) {
    
    
                unlink(x);
                return true;
            }
        }
    } else {
    
    
        for (Node<E> x = first; x != null; x = x.next) {
    
    
            if (o.equals(x.item)) {
    
    
                unlink(x);
                return true;
            }
        }
    }
    return false;
}

Step 2: Remove the node, rebuild the linked list structure, and set the current linked list data to null, and return the removed node;

E unlink(Node<E> x) {
    
    
    final E element = x.item;
    final Node<E> next = x.next;
    final Node<E> prev = x.prev;
    if (prev == null) {
    
    
        first = next;
    } else {
    
    
        prev.next = next;
        x.prev = null;
    }
    if (next == null) {
    
    
        last = prev;
    } else {
    
    
        next.prev = prev;
        x.next = null;
    }
    x.item = null;
    return element;
}

The above is the analysis of the partial structure of the source code of the LinkedList double-linked list in Java. This kind of code is too much and I always feel that the code I wrote is not Java.

Four, circular linked list

In the singly linked list, the pointer field NULL of the terminal node is changed to point to the head node or the start node, thus forming a circular linked list:

A structure of a circular linked list, which is characterized in that the pointer field of the last node in the list points to the head node, and the entire linked list forms a ring.

Five, source code address

GitHub·地址
https://github.com/cicadasmile/model-arithmetic-parent
GitEE·地址
https://gitee.com/cicadasmile/model-arithmetic-parent

Recommended reading: Algorithms and data structures

Article title
Structure and algorithm: sparse array and two-dimensional array conversion
Structure and algorithm: queue and stack structure
Algorithm application: RSA algorithm, encryption and decryption, detailed explanation of signature verification process
Algorithm application: recursive algorithm, processing business data under tree structure

Guess you like

Origin blog.csdn.net/cicada_smile/article/details/108662273