[Data structure] Simulate the implementation of a doubly linked list

You have to work really hard to appear effortless 


Table of contents

1. Simulate the implementation of a doubly linked list 

1.1 Internal class of DLinkedList

1.2 Member properties of DLinkedList

1.3 Member method of DLinkedList

1.3.1 Insert a new node at the beginning of the linked list

1.3.2 Insert a new node at the end of the linked list 

1.3.3 Calculate the number of nodes

1.3.4 Insert a new node at any position in the linked list

1.3.5 Find whether there is specified data in the linked list

1.3.6 Delete the node of the specified data that appears for the first time

1.3.7 Delete all nodes with specified data

 1.3.8 Print linked list

1.3.9 Clear linked list


1. Simulate the implementation of a doubly linked list 

The bottom layer of LinkedList is a doubly linked list, so let's implement a doubly linked list

We first need to create a class to implement such a linked list:

public class DLinkedList {

}

 Next, we need to put all the process of implementing the linked list in the DLinkedList class

1.1  Internal class of DLinkedList

We know that the linked list uses nodes to store data, and also uses nodes to realize the link between nodes

Then we now need to create an inner class in the DLinkedList class  as a node class 

//结点
private class Node {
    private int val;//数据
    private Node prev;//指向前一个结点
    private Node next;//指向后一个结点

    public Node(int val) {
        this.val = val;
    }
}
  • data: used to store data
  • prev: Used to store the address of the previous node, so as to achieve a two-way link between nodes
  • next: used to store the address of the next node, so as to achieve a two-way link between nodes
  • Construction method: Every time a node class is instantiated, the construction method needs to be called to put the data into the data field

1.2  Member properties of DLinkedList

Define a head variable of node type to record the head node, and define a tail variable of node type to record the tail node 

private Node head;//头结点
private Node tail;//尾结点

1.3  Member method of DLinkedList

1.3.1 Insert a new node at the beginning of the linked list

To insert a node at the beginning of the linked list, you first need to instantiate a node according to the data data, and then judge whether the linked list is an empty linked list . If it is an empty linked list , then this node is both the first node and the last node . If it is not an empty linked list, directly let the back pointer field of this node store the address of the head node, let the head front pointer field store the address of this node , and then make head equal to this node , because this node becomes the first Node

//头插法
public void addFirst(int data) {
    Node tmpNode = new Node(data);
    if (this.head == null) {
        this.head = tmpNode;
        this.tail = tmpNode;
    } else {
        tmpNode.next = this.head;
        this.head.prev = tmpNode;
        this.head = tmpNode;
    }
}

1.3.2 Insert a new node at the end of the linked list 

To insert a node at the beginning of the linked list, you first need to instantiate a node according to the data data, and then judge whether the linked list is an empty linked list . If it is an empty linked list , then this node is both the first node and the last node . If it is not an empty linked list, directly let the front pointer field of this node store the address of tail , let the back pointer field of tail store the address of this node , and then make tail equal to this node , because this node becomes the last node

//尾插法
public void addLast(int data) {
    Node tmpNode = new Node(data);
    if (this.head == null) {
        this.head = tmpNode;
        this.tail = tmpNode;
    } else {
        tmpNode.prev = this.tail;
        this.tail.next = tmpNode;
        this.tail = tmpNode;
    }
}

1.3.3 Calculate the number of nodes

First judge whether the linked list is an empty linked list, if it is empty, return 0 directly. Otherwise, if it is not empty, traverse the linked list to count how many nodes there are, and return the number of nodes directly after the traversal 

Note: tail.next is the next node of the last node, when cur == tail.next indicates that the linked list has been traversed

//结点个数
public int size() {
    if (this.head == null) {
        return 0;
    }
    Node cur = this.head;
    int count = 0;
    while (cur != this.tail.next) {
        count++;
        cur = cur.next;
    }
    return count;
}

1.3.4 Insert a new node at any position in the linked list

First judge whether the insertion position is legal, if not, return false directly . Otherwise, it is legal to judge whether the inserted position is the first node , and if so, insert a new node at the beginning of the linked list . Otherwise, judge whether the inserted position is the last node , and if so, insert a new node at the end of the linked list . Otherwise, to insert a new node in the middle of the linked list , you first need to instantiate a node according to the data data, then traverse the linked list to find the position of the index , and let the front pointer field of the new node store the value of the previous node at the index position Address, let the back pointer field of the previous node store the address of the new node, let the back pointer field of the new node store the address of the node at the index position, and let the front pointer field of the node at the index position store the address of the new node address

//任意位置插入,第一个数据节点为0号下标
public boolean addIndex(int index,int data){
    //判断位置是否合法
    if (index < 0 || index >= size()) {
        return false;
    }
    //判断是否为头插
    if (index == 0) {
        addFirst(data);
        return true;
    }
    //判断是否为尾插
    if (index == size() - 1) {
        addLast(data);
        return true;
    }
    //中间插
    Node tmpNode = new Node(data);
    Node cur = this.head;
    while (index != 0) {
        cur = cur.next;
        index--;
    }
    tmpNode.prev = cur.prev;
    cur.prev.next = tmpNode;
    tmpNode.next = cur;
    cur.prev = tmpNode;
    return true;
}

1.3.5 Find whether there is specified data in the linked list

Traverse the linked list directly, if there is, return true directly, otherwise return false 

//查找是否包含关键字key是否在单链表当中
public boolean contains(int key) {
    Node cur = this.head;
    while (cur != this.tail.next) {
        if (cur.val != key) {
            cur = cur.next;
        } else {
            return true;
        }
    }
    return false;
}

1.3.6 Delete the node of the specified data that appears for the first time

First judge whether the linked list is null l, otherwise, judge whether the node of the specified data is the first node of the linked list, if it is directly let head be equal to head.next . Otherwise, it is judged whether the node of the specified data is the last node of the linked list, and if it is, directly make tail equal to tail.next . Otherwise, traverse the linked list to find the node to be deleted, let the back pointer field of the node before the node to be deleted store the address of the node after the node to be deleted, and let the node after the node to be deleted The previous pointer field of the node to be deleted can store the address of the previous node of the node to be deleted, and then return directly, because only the first occurrence is deleted. Otherwise there is no such node

//删除第一次出现关键字为key的节点
public void remove(int key) {
    if (this.head == null) {
        return;
    }
    if (this.head.val == key) {
        this.head = this.head.next;
        return;
    }
    if (this.tail.val == key) {
        this.tail = this.tail.prev;
        return;
    }
    Node cur = this.head;
    while (cur != this.tail.next) {
        if (cur.val == key) {
            cur.prev.next = cur.next;
            cur.next.prev = cur.prev;
            return;
        } else {
            cur = cur.next;
        }
    }
}

1.3.7 Delete all nodes with specified data

First judge whether the linked list is null l, if it is empty, return directly . Otherwise, judge whether the linked list has only one node and this node is the node to be deleted . If so, both head and tail point to this node, then let head and tail point to null directly , and then delete. Otherwise, start traversing from the second node . If you traverse to the node with the specified data, let the back pointer field of the node before the node to be deleted store the address of the node after the node to be deleted. The front pointer field of the node after the deleted node can store the address of the previous node of the node to be deleted . Only after traversing to the penultimate node of the linked list will the loop be jumped out, and then the first node will be judged after jumping out of the loop. Whether a node is a node to be deleted, if it is directly let head be equal to head.next , and then judge whether the last node is a node to be deleted, if it is directly lettail equals tail.next

Note: If the linked list has multiple nodes, first delete the node with the specified data in the middle, and then judge whether the first node is to be deleted and whether the last node is to be deleted 

//删除所有值为key的节点
public void removeAllKey(int key) {
    if (this.head == null) {
        return;
    }
    //判断链表只要一个结点,且这个结点的值等于key
    if (this.head.val == key && this.head.next == null) {
        this.head = null;
        this.tail = null;
        return;
    }
    //删除中间等于key的结点
    Node cur = this.head.next;
    while (cur != this.tail) {
        if (cur.val == key) {
            cur.prev.next = cur.next;
            cur.next.prev = cur.prev;
        }
        cur = cur.next;
    }
    //第一个结点等于key删除
    if (this.head.val == key) {
        this.head = this.head.next;
    }
    //最后一个结点等于key删除
    if (this.tail.val == key) {
        this.tail = this.tail.prev;
    }
}

 1.3.8 Print linked list

First judge whether the linked list is null , if it is directly print null , and then return . Otherwise, traverse the linked list and print the data  in the node data field sequentially

//打印
public void display() {
    if (head == null) {
        System.out.println("null");
        return;
    }
    Node cur = this.head;
    while(cur != this.tail.next) {
        System.out.print(cur.val + " ");
        cur = cur.next;
    }
    System.out.println();
}

1.3.9 Clear linked list

Traverse once, clear the front pointer field and back pointer field of each node in turn , let them all point to null , let head equal to null , tail equal to null , so that each node of the entire linked list is not pointed to, compile The device will directly recycle

//清除链表
public void clear() {
    if (this.head == null) {
        return;
    }
    Node cur = this.head;
    while (cur != this.tail.next) {
        Node tmp = cur.next;
        cur.next = null;
        cur.prev = null;
        cur = tmp;
    }
    this.head = null;
    this.tail = null;
}

Guess you like

Origin blog.csdn.net/m0_66488562/article/details/127360735