LinkedList (concept, usage, traversal, and differences from ArrayList)

Posted by dc277 on Wed, 27 Oct 2021 12:41:16 +0200

**List implementation class 2 ---------- LinkedList**

When inserting or deleting elements at any position of ArrayList, the subsequent elements need to be moved forward or backward as a whole. The time complexity is O(n) and the efficiency is relatively low. Therefore, another structure is introduced into Java collection: LinkedList, that is, linked list structure;

LinkedList introduction

LinkedList is a common class. The bottom layer adopts a linked List structure. It inherits from AbstractList and implements interfaces such as List, Deque, clonable and Serializable;

LinkedList usage

Two construction methods of LinkedList

Because the underlying structure is a linked list, there is no capacity, so the construction method is one less than ArrayList;

  • No parameter construction LinkedList()
 List<Integer> list1=new LinkedList<>();
  • Use elements in other collections to construct: public LinkedList (Collection <? Extensions E > C)
 List<String> al = new ArrayList<>();
        al.add("111");
        al.add("222");
       //Use other container construction
       List<String> list1=new LinkedList<>(al);
       System.out.println(list1); //[111, 222]

Common methods for LinkedList

(1) Public Boolean add (e): insert element e at the tail

 List<String> list=new LinkedList();
       list.add("0000");
       list.add("1111");
     System.out.println(list);  //[0000, 1111]

(2) Public void add (int index, e): insert e at the index position

 List<String> list=new LinkedList();
     list.add("0000");
     list.add("1111");
     list.add(0,"5555");
     System.out.println(list); //[5555, 0000, 1111]

(3) Public Boolean addall (collection <? Extensions E > c): insert the element in c at the end

//Insert all the elements in the list into list1
   List<String> list=new LinkedList();
        list.add("0000");
        list.add("1111");
        List<String> list1=new LinkedList<>();
        list1.addAll(list);  
        System.out.println(list1); //[0000,1111]

(4) public int size(): get the number of valid elements

   System.out.println(list.size());

(5) public E remove(int index): deletes the index location element

 List<String> list=new LinkedList();
        list.add("0000");
        list.add("1111");
        list.remove(1);
        System.out.println(list); //[0000]

(6) Public Boolean remove (e): deletes the specified element e

 List<String> list=new LinkedList();
        list.add("0000");
        list.add("1111");
        list.remove("0000");
        System.out.println(list);//[1111]

(7) Public Boolean contains (e): whether the element e is included

 List<String> list=new LinkedList();
     list.add("0000");
     list.add("1111");
     //Include return true
     System.out.println(list.contains("0000")); 
      //Not included, return false
    System.out.println(list.contains("9999"));

(8) public E get(int index): get the index location element

List<String> list=new LinkedList();
      list.add("0000");
      list.add("1111");
   System.out.println(list.get(1)); //1111

(9) Public e set (int index, e): set the index location element to E

List<String> list=new LinkedList();
        list.add("0000");
        list.add("1111");
        list.set(1,"2222");
     System.out.println(list);//[0000, 2222]

(10) Public int indexof (E, e): find from front to back and return the subscript of the first e occurrence

List<String> list=new LinkedList();
        list.add("0000");
        list.add("3333");
        list.add(1,"0000");
    System.out.println(list.indexOf("0000"));//0

(11) Public int lastIndexOf (E, e): find from back to front and return the subscript of the first e occurrence

List<String> list=new LinkedList();
        list.add("0000");
        list.add("3333");
        list.add(1,"0000");
     System.out.println(list.lastIndexOf("0000")); // 1

(12) Public list < E > sublist (int fromindex, int toindex): intercept the [fromIndex,toIndex) part

 List<String> list=new LinkedList();
        list.add("0000");
        list.add("1111");
        list.add("2222");
        list.add("3333");
        list.add("4444");
  System.out.println(list.subList(1,4));//[1111, 2222, 3333]

(13) public boolean isEmpty(): determines whether the linked list is empty

 System.out.println(list.isEmpty());

(14) public void clear(): clear

 list.clear();
System.out.println(list.size()); //0

Traversal of LinkedList

Two traversal modes:
foreach
Iterator traversal

package day20211018;
import java.util.List;
import java.util.LinkedList;
import java.util.ListIterator;
public class Test {
    public static void main(String[] args) {
        LinkedList<Integer> list = new LinkedList<>();
        list.add(1);
        list.add(2);
        list.add(3);
        list.add(4);
        // foreach traversal
        for (int e:list) {
            System.out.print(e + " ");
        }
        System.out.println(); // 1 2 3 4
            // Iterator traversal
            ListIterator<Integer> it = list.listIterator();
            while(it.hasNext()){
                System.out.print(it.next()+ " ");
            }
            System.out.println(); //1 2 3 4
    }
}

Supplement - linked list

Concept of linked list

Physically, linked list is a discontinuous storage structure;
Logically, the logical order of data elements is linked by references in the linked list;
Examples in life: a structure similar to a train

The elements in the linked list are stored in nodes one by one;

The node contains two fields:
Value: the value range of the element in each node
Next: used to point to the next node

It should be noted that each node is an object, and next is only a reference, not an object;

Common structure of linked list

  • Unidirectional linked list and bidirectional linked list

One way linked list:

Bidirectional linked list:

  • Leading linked list and non leading linked list

No lead node:

Lead node linked list:

  • Circular linked list and acyclic linked list

Acyclic linked list:

Circular linked list:

Note: there are 8 structures combined

Linked list implementation

  • (1) Simulate the implementation of a single linked list without leading nodes
package day20211018;

   //Simulation Implementation: single linked list without leading node
public class SingleLinkList<E> {
   public static class Node<E> {
      E value;
      Node<E> next;

      //Construction method
      public Node(E value) {
         this.value = value;
      }
   }
      Node<E> head; //Used to point to the first valid node in the linked list
      //Gets the effective length of the single linked list
      public int size(){
         Node<E> cur=head;
         int count=0;
         while(null != cur){
            count++;
            cur=cur.next;
         }
         return count;
      }


      // Head insert e
      public void addFirst(E e){
         Node<E> newNode=new  Node<>(e);
         if(null==head){
            head=newNode;
         }else{
            newNode.next=head;
            head=newNode;
         }
      }


      // Tail insert e
      public void addLast(E e) {
         Node<E> newNode = new Node<>(e);
         if (null == head) {
            head = newNode;
         } else {
            //Find the last node
            //cur points to the first node
            Node<E> cur = head;
            //pre to mark the position of the last node
            Node<E> pre = null;
            while (null != cur) {
               pre = cur;
               cur = cur.next;
            }
            //Insert new node
            pre.next = newNode;
         }
      }
      //Insert e at any position, and the first data node is position 0
      public boolean addIndex(int position,E e){
         //1. Check whether the parameters are legal
         if(position < 0 || position >= 4){
            throw new IllegalArgumentException("Illegal parameter");
         }
         if(0==position){
            addFirst(e);
            return true;
         }
         //2. Find the node at position and save the previous one (insert it in front of position)
         Node<E> cur=head;
         Node<E> pre=null;
         while(0 != position){
            pre=cur;
            cur=cur.next;
            position--;
         }
         //3 insert new node

         Node<E> newNode=new Node<E>(e);
         newNode.next=cur;
         pre.next=newNode;

         return true;
      }

      //Delete the node with keyword e for the first time
      public void remove(E e){
         Node<E> cur=head;
         Node<E> prev=null;
         //prev is used to mark cur
         while(null != cur){
            if(e.equals(cur.value)){
               cur.value=null;
               if(prev==null){
                  //Note: the first node is deleted
                 head=cur.next;
            }else{
                  //Delete other nodes
                  prev.next=cur.next;
               }
            return;
            }
            prev=cur;
            cur=cur.next;
         }
      }

      //Delete all nodes with the value e
     public void removeAllKey(E e) {
        //Time complexity O(N^2)
        /*while(contains(e)){
           remove(e);
        }*/
        Node<E> cur=head;
        Node<E> prev=null;
        while(null!= cur){
           if(e.equals(cur.value)){
              //Delete Vertex 
              cur.value=null;
              if(prev==null){
                 head=cur.next;
                 cur=head;
              }else{
                 prev.next=cur.next;
                 cur=prev.next;
              }

           }else{
              prev=cur;
              cur=cur.next;
           }

        }
      }

      //Find whether to include the keyword e
      public boolean contains(E e) {
         Node<E> cur=head;
         while(null!=cur){
            if(e.equals(cur.value)){
               return true;
            }
            cur=cur.next;
         }
         return false;
      }
     
      @Override
      public String toString(){
         Node<E> cur=head;
         String s="[";
         while(null!= cur){
            s+=cur.value;
            if(null !=cur.next){
               s+=",";
            }

            cur=cur.next;
         }
         s+="]";
         return s;
      }

      public static void main(String[] args) {
         SingleLinkList<Integer> s=new SingleLinkList<>();
         System.out.println(s); //[]
         //Test tail insertion
         s.addLast(1);
         s.addLast(2);
         s.addLast(3);
         s.addLast(4);
         System.out.println(s); //[1,2,3,4]
         System.out.println(s.size()); //4
         //Test whether element e is included
         System.out.println(s.contains(2)); //true
         System.out.println(s.contains(5)); //false
         //Test head plug
         s.addFirst(0);
         System.out.println(s);  //[0,1,2,3,4]
         //Test insertion anywhere
         s.addIndex(0,0);
         System.out.println(s); //[0,0,1,2,3,4]
         s.addIndex(3,5);
         System.out.println(s); //[0,0,1,5,2,3,4]
         //Delete all elements with value 0
         s.removeAllKey(0);
         System.out.println(s); //[1,5,2,3,4]
         //Test remove
         s.remove(5);
         System.out.println(s); //[1,2,3,4]
      }
   }


Move your little hand and poke it down~~

Summary - relationship and difference between ArrayList and LinkedList

  • Similarities: both implement the List interface;
  • The differences are reflected in the following aspects:

(1) Because ArrayList bottom layer uses array to store elements, it supports random access;
(2) The LinkedList bottom layer adopts a two-way linked list structure and does not support random access;
(3) ArrayList supports capacity expansion, but LinkedList does not have the concept of capacity expansion;
(4) In terms of storage space: ArrayList is physically continuous, LinkedList is logically continuous, but physically not necessarily continuous;
(5) When inserting and deleting elements at any position, ArrayList can only be inserted after moving the elements and vacating the position. Therefore, the time complexity is O(N) and the efficiency is slow;
LinkedList only needs to modify the direction of the reference. The time complexity is O(1) and the efficiency is high;
In other words, when efficiently accessing elements, give priority to ArrayList, and * * LinkedList * * *. When inserting and deleting elements at any position