Linear list (array, linked list, queue, stack) detailed summary

Time:2021-2-27

Linear table is a very basic and important data structure

Next, I will make a detailed summary of these four data structures, in which the linked list is implementedMore than ten kindsCommon operations. Hope to help you.

1. Array

Array is a linear table data structure. It uses a group of continuous memory space to store a group of data with the same type.
Note: 1. Array is a kind ofLinear table;②.Continuous memory space and the same type of data
Because of the second property, arrays supportRandom accessAccording to the following table, the time complexity of random access is O (1); but at the same time, it makes deleting in the array and inserting data need a lot of data moving.

Inefficient “insertion” and “deletion”

Insert operation

If the length of the array is n, we need to insert a data into the k-th position of the array. We need to move the k-th to n-th elements back one bit in order.
In the best case, the time complexity is O (1), which corresponds to inserting elements at the end of the array;
The worst-case time complexity is O (n), which corresponds to inserting elements at the beginning of the array;
The average time complexity is O (n), because the probability of inserting elements in each position is the same, so (1 + 2 + 3 +…) +n)/n=O(n);
But according to our needs, there is a specific scenario. If the data of an array is ordered, we must do that when inserting it. However, if the data stored in the array has no regularity, the array is just regarded as a dataA collection of stored dataWe can have a clever way:
Move the k-th element directly to the end of the array element, and put the new data directly into the k-th position (isn’t it very simple). At this time, the complexity of inserting elements is O (1).

Delete operation

Like the insert operation, the delete operation also needs to move data in order to ensure the continuity of memory.
In the best case, the time complexity is O (1), which corresponds to deleting the elements at the end of the array;
The worst-case time complexity is O (n), which corresponds to deleting the elements at the beginning of the array;
The average time complexity is O (n), because the probability of deleting each element is the same, so (1 + 2 + 3 +…) +n)/n=O(n);
Of course, in some special cases, we don’t have to carry out itcomplexDelete operation for. We just will need to delete the datarecordAndPretend it was deleted. Until the array has no more space to store data, we can trigger a real delete operation.

In fact, this is similar to the garbage can in life. Garbage doesn’t disappear, it’s just discarded“sign”It becomes garbage, and it doesn’t clean up until the bin is full.

Guard against array access out of bounds

In C language, as long as it is not limited to access memory, all memory space can be freely accessed. If we neglect it, we will have serious consequences. Of course, Java will detect it automatically.

2. Linked list

  • Linked list node representation
  • Print single linked list
  • The single linked table inserts the node according to the index
  • Gets the length of a single linked list
  • Print the length of a single linked list
  • Single linked table delete the node of the specified index
  • Single linked list element search, return whether there is a Boolean value
  • A single linked table deletes subsequent nodes of the specified index
  • Single linked list inversion
  • Single linked list inversion recursively
  • Check whether there are rings in the linked list
  • Delete the last K node
  • Find the middle node
  • Ordered list merging

Linked list node representation

public class Node{
    int data;
    Node Next;
}

Print single linked list

public class Method {
    //Print single linked list
    public static void PrintNode (Node list){
        for(Node x=list;x!=null;x=x.Next)
        System.out.print(x.data+" ");
        System.out.println();
    }

The single linked table inserts the node according to the index

public static Node insert(Node first,int index,Node a){
        Node ret = new Node();
        ret.Next=first ; // create a virtual head node
        Node p=ret;
        while((index--)!=0) p=p.Next;
        //Complete the insertion operation of the node
        a.Next=p.Next;
        p.Next=a;
        //Returns the real chain header node address
        return  ret.Next ; // the function returns the head node of the linked list
    }

Gets the length of a single linked list

    public static int GetLength(Node first){
        int n=0;
        for(Node x=first;x!=null;x=x.Next){
            ++n;
        }
        return n;
    }

Print the length of a single linked list

    public static void PrintLength(Node first){
        System.out.println("Length : "+GetLength(first));
    }

Single linked table delete the node of the specified index

public static Node Delete(Node first,int index){
        if(index<0||index>=GetLength(first)) return first;
        else{
        Node ret=new Node();
        ret.Next=first;
        Node p=ret;
        while((index--)!=0) p=p.Next;
        //Delete the node
        p.Next=p.Next.Next;
        return ret.Next;
        }
    }

Single linked list element search, return whether there is a Boolean value

    public static boolean Find(Node first,int key){
        for(Node x=first;x!=null;x=x.Next){
            if(x.data==key) return true;
        }
        return false;
    }

A single linked table deletes subsequent nodes of the specified index

    public static void RemoveAfter(Node first,int index){
        Node ret=new Node();
        ret.Next=first;
        Node p=ret;
        while((index--)!=0) p=p.Next;
        p.Next.Next=null;

    }

Single linked list inversion

    public static Node  reverse(Node list){
        Node curr=list,pre=null;
        while(curr!=null){
            Node next=curr.Next;
            curr.Next=pre;
            pre=curr;
            curr=next;
        }
        return pre;
    }

Single linked list inversion recursively

public static Node reverseRecursively(Node head){
        if(head==null|| head.Next==null )Return head; // recursion termination condition. Returns the head node of the inverted linked list
        Node reversedListHead=reverseRecursively(head.Next);
        head.Next.Next=head ; // change the pointing order between the two nodes
        head.Next=null;
        Return reversedlisthead; // returns the inverted chain header node
    }

Check whether there are rings in the linked list

    public static boolean checkCircle(Node list){
        if(list==null) return false;

        Node fast=list.Next;
        Node slow=list;

        while(fast!=null&&fast.Next!=null){
            fast=fast.Next.Next;
            slow=slow.Next;

            if(slow==fast) return true;
        }
        return false;
    }

Delete the last K node

public static Node deleteLastKth(Node list,int k){
        //Two pointers, fast and slow, are used to judge if there is a difference of K positions between them fast.Nest=null , which means that the position of slow is the last K node
        Node fast=list;
        int i=1;
        while(fast!=null&&i<k){
            fast=fast.Next;
            ++i;
        }

        if(fast==null) return list;

        Node slow=list;
        Node prev=null;
        while(fast.Next!=null){
            fast=fast.Next;
            prev=slow;
            slow=slow.Next;
        }

        if(prev==null){
            list=list.Next;
        }else{
            prev.Next=prev.Next.Next;
        }
        return list;
    }

Find the middle node

    public static Node findMiddleNode(Node list){
        if(list==null) return null;

        Node fast=list;
        Node slow=list;

        while(fast!=null&&fast.Next!=null){
            fast=fast.Next.Next;
            slow=slow.Next;
        }

        return slow;
    }

Ordered list merging

    public static Node mergeTwoLists(Node l1,Node l2){
        Node soldier=new Node();
        Node p=soldier;

        while(l1!=null&&l2!=null){
            if(l1.data<l2.data){
                p.Next=l1;
                l1=l2.Next;
            }
            else{
                p.Next=l2;
                l2=l2.Next;
            }
            p=p.Next;
        }

        if(l1!=null){ p.Next=l1;}
        if(l2!=null){ p.Next=l2;}
        return soldier.Next;
    }

3. Stack

  • Sequential stack
  • Chain stack

1. Sequential stack based on array

  • Constructors
  • Stack operation
  • Stack out operation
  • Print operation
package Stack;

//Implementation of sequential stack based on array
public class ArrayStack {
    private int[] items;
    Private int count; // the number of elements in the stack
    Private int n; // stack size
  //Initialize the array and apply for an array space of size n
public ArrayStack(int n){
    this.items=new int[n];
    this.n=n;
    this.count=0;
}

//Stack operation
public boolean push(int item){
    //Insufficient array space, return false directly, fail to stack
    if(count==n) return false;
    //Put the data in the place with the subscript count, and add one to count
    items[count]=item;
    ++count;
    return true;
}

//Stack out operation
public int pop(){
    //If the stack is empty, return - 1 directly;
    if(count==0) return -1;
    //Returns the array elements with the subscript count-1, and the number of elements in the stack count minus one
    int tmp=items[count-1];
    --count;
    return tmp;
}
public void PrintStack(){
    for(int i=count-1;i>=0;--i){
        System.out.print(items[i]+" ");
    }
    System.out.println();
    }
}

2. Chain stack based on linked list

  • Stack operation
  • Stack out operation
  • Print operation
package Stack;

public class LinkedListStack {
    Private node top; // top of stack (recently added element)
    Private int n; // number of elements
    private class Node{
        //The nested class of node is defined
        int data;
        Node Next;
    }
    public boolean isEmpty(){
        return top==null;
    }
    public int size(){
        return N;
    }

    public void push(int data){
        /*Node newNode=new Node();
        //Determine whether the stack is empty
        //if(top==null) 
        newNode=top;
        top.data=data;
        top.Next=newNode;
        N++;*/
        Node newNode=top;
        top=new Node();
        top.data=data;
        top.Next=newNode;
        ++N;
    }
    public int pop(){
        //Remove element from top of stack
        If (top = = null) return - 1; // here - 1 means there is no data in the stack
        int data=top.data;
        top=top.Next;
        N--;
        return data;
    }
    public void PrintStack(){
        for(Node x=top;x!=null;x=x.Next){
            System.out.print(x.data+" ");
        }
        System.out.println();
    }

}

4. Normal queue

  • Ordinary queue based on array
  • Queue based on linked list
  • Implementation of circular queue based on array

1. Ordinary queue based on array

  • Constructors
  • Team operation
  • Out of line operation
  • Print elements in queue
package Queue;

//Using array to realize queue
public class ArrayQueue {
    //Array: items, array size: n
    private int[] items;
    private int n=0;
    //Head is the team head subscript and tail is the team tail subscript
    private int head=0;
    private int tail=0;

    //Apply for an array of capacity
    public ArrayQueue(int capacity){
        items=new int[capacity];
        n=capacity;
    }

    //Join the team (1), Basic Edition
    public boolean enqueue(int item){
        //If tail = = n, there is no space at the end of the queue
        if(tail==n) return false;
        items[tail]=item;
        ++tail;
        return true;
    }

    //Team entry (2), improved version
    public boolean enqueue1(int item){
        //If tail = = n, there is no space at the end of the queue
        if(tail==n){
            //Tail = = n & & head = = 0, indicating that the whole queue is full
            if(head==0) return false;
            //Data migration
            for(int i=head;i<tail;++i){
                items[i-head]=items[i];
            }
            //Update the head and tail after moving
            tail=tail-head;
            head=0;
        }
        items[tail]=item;
        ++tail;
        return true;
    }

    //Get out of the team
    public int dequeue(){
        //If head = = tail, the queue is empty
        If (head = = tail) return - 1; // here - 1 means that the queue is empty
        int ret=items[head];
        ++head;
        return ret;
    }

    //Print queue
    public void PrintQueue(){
        for(int i=head;i<tail;++i){
            System.out.print(items[i]+" ");
        }
        System.out.println();
    }

}

2. Queue based on linked list

  • Constructors
  • Team operation
  • Out of line operation
  • Print elements in queue
package Queue;

//Queue based on linked list
public class LinkedListQueue {

    Private node head; // link to the earliest node added
    Private node tail; // link to the recently added node
    Private int n; // number of elements in the queue
    private class Node{
        //The nested class of node is defined
        int data;
        Node Next;
    }
    public boolean isEmpty(){
        return head==null;
    }
    public int size(){ return N;}

    //Add elements to the end of the table, that is, join the queue
    public void enqueue(int data){
        Node newNode=tail;
        tail=new Node();
        tail.data=data;
        tail.Next=null;
        if(isEmpty()) head=tail;
        else newNode.Next=tail;
        ++N;
    }
    public int dequeue(){
        //Remove element from header
        int data=head.data;
        head=head.Next;
        if(isEmpty()) tail=null;
        N--;
        return data;
    }

    //Printout queue elements
    public void PrintQueue(){
        for(Node x=head;x!=null;x=x.Next){
            System.out.print(x.data+" ");
        }
        System.out.println();
    }
}

3. Circular queue based on array

  • Constructors
  • Team operation
  • Out of line operation
  • Print elements in queue
package Queue;

public class CircularQueue {
    //Array items, array size n
    private int[] items;
    private int n=0;
    //Head is the team head subscript and tail is the team tail subscript
    private int head=0;
    private int tail=0;

    //Apply for an array of capacity
    public CircularQueue(int capacity){
        items = new int[capacity];
        n=capacity;
    }

    //Join the team
    public boolean enqueue(int item){
        //The queue is full
        if((tail+1)%n==head) return false;
        items[tail]=item;
        Tail = (tail + 1)% n; // loop counting
        return true;
    }

    //Get out of the team
    public int dequeue(){
        //If head = = tail, the queue is empty
        If (head = = tail) return - 1; // if - 1, the queue is empty
        int ret=items[head];
        head=(head+1)%n;
        return ret;
    }

    //Print queue
    public void PrintQueue(){
        if(n==0) return;
        for(int i=head;i%n!=tail;i=(i+1)%n){
            System.out.print(items[i]+" ");
        }
        System.out.println();
    }
}

explain

The article code is too much, I originally hoped to divide it into several articles to write, but for some reasons, finally put them together, slightly bloated. The code has been tested by test cases, and there should be no errors.

If the experience is not very good, you can move my stepsGithubIt looks good inside.

Digression: for algorithm beginners, recommend a very nice bookAlgorithm Fourth EditionAll kinds of pictures in it are very detailed. If you need an electronic file, reply backAlgorithm 4You can get the download link. Backstage replyAlgorithm 01Send you an algorithm and data structure mind map. Finally, I hope we can make progress and grow together!