Linked list and implementation of Java data structure

Posted by programming_passion on Mon, 07 Feb 2022 09:06:02 +0100

The previously learned sequence table query is very fast, and the time complexity is O(1), but the efficiency of addition, deletion and modification is very low, because each addition, deletion and modification will move the elements. You can use another storage method - chain storage structure.

Linked list is a non continuous and non sequential storage structure on physical storage unit. A linked list consists of a sequence of nodes (each element in the list becomes a node).

Node API design:

Class nameNode
Construction methodNode (T, node next) creates a node object
Member variable

T item: store data

Node next: points to the next node

Node class:

public class Node<T>{
    Node next;
    private T item;

    public Node(Node next, T item) {
        this.next = next;
        this.item = item;
    }
}

Generate linked list:

public class TestNode {
    public static void main(String[] args) {
        // Generation node
        Node<Integer> one = new Node<Integer>(null,12);
        Node<Integer> two = new Node<Integer>(null,16);
        Node<Integer> three = new Node<Integer>(null,11);
        Node<Integer> four = new Node<Integer>(null,10);
        //Generate linked list
        one.next = two;
        two.next = three;
        three.next =four;
    }
}

1. Single linked list

Unidirectional linked list is a kind of linked list. It is composed of multiple nodes. Each node is composed of a data field and a pointer. The data field is used to store data and the pointer field is used to point to subsequent nodes.

The data field of the head node of the linked list does not store data, and the pointer field points to the first node that actually stores data.

API design of one-way linked list

Class nameLinkList
Construction methodLinkList(): create a LinkList object
Member variable

private Node head; Record first node

private int N; Record the length of the linked list

Member inner classprivate class Node; Node class
Member method
public void clear()Empty linked list
public boolean isEmpty()Judge whether the linked list is empty, and return true if yes
public int length()Get the number of elements in the linked list
public T get(int i)Read and return the value of the ith element in the linked list

public void insert(T t)

Insert an element into the linked list
public void insert(T t,int i)Insert a data element with the value of t at the i position of the linked list
public T remove(int i)Delete and return to delete the ith data element in the linked list
public int indexof(T t)Returns the sequence number of the specified data element that appears for the first time in the linked list. If it does not exist, it returns - 1

Java code implementation of one-way linked list

package com.ycy.Algorithm.LinkList;


import java.util.Iterator;

/**
 * The head of the linked list cannot be moved
 * @param <T>
 */
public class LinkList<T> implements Iterable<T>{

    private Node head;//The head node of the linked list cannot be moved
    private int N;//Number of nodes
    public LinkList() {
        this.head = new Node(null,null);
        N = 0;
    }
    /**
     * Node inner class
     */
    private class Node{
        //Store data
        T item;
        //Next node
        Node next;
        public Node(T item,Node next) {
            this.item = item;
            this.next = next;
        }

    }
    /**
     * Empty linked list
     */
    public void clear(){
        head.item=null;
        head.next=null;// If the head node next is null, it is an empty linked list
        this.N=0;
    }
    /**
     * Determine whether the linked list is empty
     */
    public boolean isEmpty(){
        return this.N==0;
    }
    /**
     * Get the length of the linked list
     */
    public int length(){
        return this.N;
    }
    /**
     * Read the element value at position i of the linked list and return
     */
    public T get(int i){
        //Illegality check
        if(i<0 || i > this.N){
            throw new RuntimeException("Illegal location");
        }
        // n also refers to the head node
        Node n = head;
        for(int index=0; index<i; index++){
            n = n.next;
        }
        return n.item;
    }
    /**
     * Insert data into the linked list t
     */
    public void insert(T t){
        // The head cannot be moved, otherwise the linked list cannot be found
        // You can define a temporary Node and a pointer to the head by moving the pointer
        Node n = head;
        // Get tail node
        while(true){
            // When there is just one node (header node)
            if(n.next == null){
                break;
            }
            n = n.next;
        }
        //When the table is empty, it can be inserted
        Node node = new Node(t, null);
        n.next =node;
        this.N ++;
    }

    /**
     * Insert data t at position i
     */
    public void insert(T t,int i){
        // Illegality check
        if(i < 0 || i > this.N){
            throw  new RuntimeException("Insertion position❌");
        }
        Node pre = head;
        for(int index=0;index <= i-1; index++){
            pre = pre.next;
        }
        Node current = pre.next;
        //Link the following nodes first
        Node newNode = new Node(t,null);
        pre.next = newNode;
        newNode.next = current;
        this.N++;
    }
    /**
     * Removes and returns the element value at position i
     */
    public  T remove(int i){
        // Illegality check
        if(i < 0 || i >this.N){
            throw  new RuntimeException("Error deleting location");
        }
        Node n =head;
        for(int index=0;index <= i-1;index ++){
             n = n.next;
        }
        //Node to delete
        Node curr = n.next;
        n.next = curr.next;
        this.N--;//Number of nodes minus one
        return curr.item;
    }
    //Find the position where the element t first appears in the linked list
    public int indexof(T t){
        Node n = head;
        for(int i = 0; n.next != null;i++){
            n =n.next;
            if(n.item.equals(t)){
                return i;
            }
        }
        return -1;
    }

    @Override
    public Iterator iterator() {
        return new Iterator() {
            Node n =head;
            @Override
            public boolean hasNext() {
                return n.next !=null;
            }
            @Override
            public Object next() {
                //Move down one pointer
                n = n.next;
                return n.item;
            }
        };
    }
}

Add a point: after the assignment of the linked list to the new linked list, the two linked lists will be affected. In other words, the address is assigned to it. Their operation is the same object of the same memory. Node n = head; Assign the head to N, and now the operation on N will also affect the head

It provides traversal mode and implements Iterable interface.

Test code:

public class test {
    public static void main(String[] args) {
        LinkList<Integer>linkList = new LinkList<>();
        linkList.insert(1);
        linkList.insert(2);
        linkList.insert(4);
        linkList.insert(3);
        linkList.insert(1,2);
        for (Integer i : linkList) {
            System.out.print(i+" ");
        }
    }
}

Operation results:

D:\Java\jdk-12.0.2\bin\java.exe "-javaagent:D:\IDEA\IntelliJ IDEA 2019.1\lib\idea_rt.jar=3542:D:\IDEA\IntelliJ IDEA 2019.1
1 2 1 4 3 

After learning the linked list, you still need to practice. You can brush questions on LeetCode to deepen your understanding.

2. Bidirectional linked list

Head inserting method: new nodes are always inserted in the head

It is easy to understand and can be represented by drawing

Head interpolation: in the original drawing, node is the node to be inserted

Figure after insertion:

Critical code:

Tail inserting method: new nodes are always inserted at the tail

The original drawing is as follows:

 

After inserting nodes, the figure is as follows:

Critical code:

Insert anywhere in the middle

Original image before insertion:

 

Insert into the middle of the linked list:

Critical code:

Code demonstration:

class MyLinkedList {
    Node head;//Defines the head node of a two-way linked list
    Node last;//Defines the tail node of a two-way linked list

    //Print bidirectional linked list
    public void disPlay() {
        Node cur = this.head;
        while (cur != null) {
            System.out.print(cur.val + " ");
            cur = cur.next;
        }
        System.out.println();
    }

    //Find the length of the two-way linked list (which will be used in addIndex code later)
    public int size() {
        int count = 0;
        Node cur = this.head;
        while (cur != null) {
            count++;
            cur = cur.next;
        }
        return count;
    }

    //Head insertion
    public void addFirst(int data) {
        Node node = new Node(data);//Define a node for insertion
        //1. Suppose the two-way linked list is empty
        if (this.head == null) {
            this.head = node;
            this.last = node;
        } else {
            //2. When the two-way linked list is not empty
            //I don't understand. Please look at the diagram above. It's very simple
            node.next = this.head;
            this.head.prev = node;
            this.head = node;
        }
    }

    //Tail insertion (similar to head insertion)
    public void addLast(int data) {
        //Define a node for insertion
        Node node = new Node(data);
        //1. Suppose the two-way linked list is empty
        if (this.head == null) {
            this.head = node;
            this.last = node;
        } else {
            //2. When the two-way linked list is not empty
            //The diagram above is very simple, please read it
            last.next = node;
            node.prev = last;
            last = node;
        }
    }

    //Insert anywhere
    public void addIndex(int index, int data) {//The formal parameter index is the position of the inserted element, and data is the inserted value
        //Define a node for insertion
        Node node = new Node(data);
        Node cur = this.head;//Define a cur to traverse the bidirectional linked list
        //1. Judge the legitimacy of the insertion position
        if (index < 0 || index > size()) {
            System.out.println("Illegal insertion position!!!");
            return;
        }
        //2. Assuming that the insertion position is the head node, that is, the head insertion method
        if (index == 0) {
            addFirst(data);//Call header insertion code
            return;
        }
        //3. Assuming that the insertion position is the tail node, that is, the tail insertion method
        if (index == size()) {
            addLast(data);//Call tail interpolation code
            return;
        }
        //4. At any position in the middle
        while (index != 0) {
            cur = cur.next;
            index--;
        }
        //I don't understand. Please look at the diagram above. It's very simple
        //Core code
        node.next = cur;
        node.prev = cur.prev;
        cur.prev = node;
        node.prev.next = node;
    }
}

//Node structure of bidirectional linked list
class Node {
    int val;
    Node prev;
    Node next;

    Node(int val) {
        this.val = val;
    }
}

3. Linked list inversion

public void reverse(){
        if(N==0){
        //Currently, it is an empty linked list and does not need to be reversed
            return;
        }
        reverse(head.next);
}
    /**
     * @param curr Node currently traversed
     * @return The previous node of the current node after inversion
     */
public Node reverse(Node curr){
        //The last element has been reached
        if(curr.next==null){
        //After inversion, the head node should point to the last element in the original linked list
          head.next=curr;
          return curr;
        }
       //Previous node of current node
       Node pre=reverse(curr.next);
       pre.next=curr;
       //The next node of the current node is set to null
       curr.next=null;
       //Return current node
       return curr;
}

 

Topics: Java linked list JavaSE