Code Random Notes - Linked List

Summary overview

Linked list theoretical basis

A linked list is a linear structure connected in series through pointers. Each node is composed of two parts, one is the data field and the other is the pointer field (which stores the pointer to the next node). The pointer field of the last node points to null (meaning null pointer). ).

Type of linked list 

1. Single linked list 

The pointer field in a singly linked list can only point to the next node of the node. 

2. Double linked list

Double linked list: Each node has two pointer fields, one pointing to the next node and one pointing to the previous node.

Doubly linked lists can be queried forward or backward.

3. Circular linked list

Linked list storage method

A linked list links nodes in memory through pointers in the pointer field.

        Therefore, the nodes in the linked list are not continuously distributed in the memory, but scattered at certain addresses in the memory. The allocation mechanism depends on the memory management of the operating system.

The starting node of the linked list in the above figure is 2, and the ending node is 7. Each node is distributed in different address spaces of the memory and is connected in series through pointers.

Definition of linked list

// 单链表
struct ListNode {
    int val;  // 节点上存储的元素
    ListNode *next;  // 指向下一个节点的指针
    ListNode(int x) : val(x), next(NULL) {}  // 节点的构造函数
};

Linked list operations

1. Delete node 

Just point the next pointer of node C to node E. In C++, manually release the D node and release this memory.

2. Add nodes 

It can be seen that adding and deleting linked lists are O(1) operations and will not affect other nodes.

But please note that if you want to delete the fifth node, you need to search from the head node to the fourth node and perform the deletion operation through the next pointer. The time complexity of the search is O(n).

Performance analysis

When an array is defined, its length is fixed. If you want to change the length of the array, you need to redefine a new array.

The length of the linked list does not need to be fixed, and can be dynamically added or deleted, which is suitable for scenarios where the amount of data is not fixed, frequent additions and deletions, and few queries.

203. Remove linked list elements

Problem-solving ideas and codes

Two ways to operate linked lists:

  • Use the original linked list directly to perform the deletion operation.
  • Set up a virtual head node to perform the deletion operation.

The first operation:

Directly use the original linked list to remove

        The operation methods of removing the head node and removing other nodes in a singly linked list are different. In fact, when writing code, you will also find that you need to write a separate piece of logic to handle the situation of removing the head node .

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        // 删除头结点
        while (head != NULL && head->val == val) { // 注意这里不是if
            ListNode* tmp = head;
            head = head->next;
            delete tmp;
        }

        // 删除非头结点
        ListNode* cur = head;
        while (cur != NULL && cur->next!= NULL) {
            if (cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        return head;
    }
};

The second operation:

You can set up a virtual head node to remove it with a unified logic

class Solution {
public:
    ListNode* removeElements(ListNode* head, int val) {
        ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点
        dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作
        ListNode* cur = dummyHead;
        while (cur->next != NULL) {
            if(cur->next->val == val) {
                ListNode* tmp = cur->next;
                cur->next = cur->next->next;
                delete tmp;
            } else {
                cur = cur->next;
            }
        }
        head = dummyHead->next;
        delete dummyHead;
        return head;
    }
};
  • Time complexity: O(n)
  • Space complexity: O(1)

707. Design linked list

class MyLinkedList {
public:
    MyLinkedList() {
        this->size = 0;
        this->head = new ListNode(0);
    }
    
    int get(int index) {
        if (index < 0 || index >= size) {
            return -1;
        }
        ListNode *cur = head;
        for (int i = 0; i <= index; i++) {
            cur = cur->next;
        }
        return cur->val;
    }
    
    void addAtHead(int val) {
        addAtIndex(0, val);
    }
    
    void addAtTail(int val) {
        addAtIndex(size, val);
    }
    
    void addAtIndex(int index, int val) {
        if (index > size) {
            return;
        }
        index = max(0, index);
        size++;
        ListNode *pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred->next;
        }
        ListNode *toAdd = new ListNode(val);
        toAdd->next = pred->next;
        pred->next = toAdd;
    }
    
    void deleteAtIndex(int index) {
        if (index < 0 || index >= size) {
            return;
        }
        size--;
        ListNode *pred = head;
        for (int i = 0; i < index; i++) {
            pred = pred->next;
        }
        ListNode *p = pred->next;
        pred->next = pred->next->next;
        delete p;
    }
private:
    int size;
    ListNode *head;

};

206. Reverse linked list

ListNode* reverseList(ListNode* head) {
    ListNode *cur = head; // cur 指向当前节点,从头节点开始
    ListNode *pre = NULL; // pre 指向当前节点的前一个节点,初始为空
    ListNode* temp; // 用于暂存当前节点的下一个节点

    while (cur != NULL) { // 遍历整个链表
        temp = cur->next; // 保存当前节点的下一个节点,防止断链
        cur->next = pre; // 将当前节点指向前一个节点,完成翻转操作

        // 更新 pre 和 cur 指针
        pre = cur;
        cur = temp;
    }
    return pre; // 返回翻转后的链表头节点
}

Guess you like

Origin blog.csdn.net/weixin_43200943/article/details/132226954