Definition and implementation of queues

Posted by poppy on Thu, 05 Sep 2019 07:25:12 +0200

Preface

  • Language: Java
  • Environment: IntelliJ IDEA
  • JDK Version: 1.8
  • Source code: GitHub

Definition of queue

Queue is a special linear table. It only allows deletion at the front of the table, but insertion at the back of the table. Like stack, queue is a restricted linear table. The end of the insertion operation is called the end of the queue, and the end of the deletion operation is called the head of the queue.

The characteristics of the queue:

  • First in first out (FIFO), inserting data from the end of the queue, and extracting data from the head of the queue
  • Whether it's an array or a linked list implementation, two variables (pointers) are usually required to mark the head and tail of the team.

Implementation of Queue

Array implementation queue

Several cases of array implementation queue:

The following information can be obtained from the above four situations:

  • The initial value front=rear=-1
  • Front points to the front of the first data, and rear points directly to the last data.
  • The condition for judging the queue to be empty is front==rear
  • The condition for judging a full queue is rear==maxSize-1
  • The number of valid data is rear-front
  • When entering the queue, add rear first, and then insert data at rear.
  • First add front, then fetch data from front.
public class ArrayQueue {
    private Integer maxSize = 3;    //Maximum number of objects that can be accommodated in a queue
    private Integer front = -1;  //Always point before the first data
    private Integer rear = -1;  //Point to the last data
    private Employee[] employeeQueue;   //Array for storing data
    public ArrayQueue(){
        employeeQueue = new Employee[this.maxSize];
    }
    public ArrayQueue(Integer maxSize){
        this.maxSize = maxSize;
        employeeQueue = new Employee[this.maxSize];
    }

    /**
     *  Add a data, add it to the tail, add it to return true successfully, and return false failed
     */
    public boolean addEmployee(Employee employee){
        if(this.isFull()){
            return false;
        }
        this.rear++;    //When queues add data, last needs to be moved back
        this.employeeQueue[this.rear] = employee;
        return true;
    }

    /*
     *  Get the first data and remove it from the queue
     */
    public Employee getEmployee(){
        if(this.isEmpty()){
            return null;
        }
        this.front++;   //Removing data actually moves first backwards so that it cannot access the previous array
        return this.employeeQueue[this.front];
    }

    /**
     *  Display the first data, only display, not remove from the queue
     */
    public Employee showEmployee(){
        if(this.isEmpty()){
            return null;
        }
        return this.employeeQueue[this.front+1];
    }

    /**
     * Is the queue empty?
     */
    public boolean isEmpty(){
        return this.front == this.rear;
    }

    /**
     *  Is the queue full?
     */
    public boolean isFull(){
        return this.rear == this.maxSize-1;
    }
    /**
     * Format all the data of the queue
     */
    public String formatQueue(){
        if(this.isEmpty()){
            return "[]";
        }
        String str = "";
        for(int i = this.front;i<this.rear;i++){
            str += this.employeeQueue[i+1].toString()+"\n";
        }
        return str;
    }
}

Advantage:

  • Easy to understand, easy to implement

Disadvantages:

  • Queues contain limited amounts of data
  • For a one-time queue, every data is taken out, the previous position can not be used again. If the queue is inserted into the full data, and then all data is taken out, then although the queue is theoretically empty, the actual queue capacity is already 0.

Ring Array Implementation Queue

The first way is to achieve: When front and rear are moved to maxSize-1, they are then moved to the beginning of the array to be recycled

The following information can be obtained from the above four situations:

  • The initial value front=rear=0
  • front always points to the first data, and real points to the space after the last data.
  • The condition for judging the queue to be empty is front==rear
  • The condition for judging queue full is (rear+1)%maxSize==front.
  • The number of valid data is (rear+maxSize-front)%maxSize
  • When entering the team, insert data directly at the rear, and then make the rear move backward (the model needs to be taken back)
  • When leaving the team, the data at the front is taken out directly, and then the front is moved back (the back movement needs to be modeled).
public class AnnulusArrayQueue1 {
    private Integer maxSize = 3;    //Maximum number of objects that can be accommodated in a queue
    private Integer front = 0;  //Point to the first data
    private Integer rear = 0;  //Point to the last empty area of data
    private Employee[] employeeQueue;   //Array for storing data
    public AnnulusArrayQueue1(){
        employeeQueue = new Employee[this.maxSize];
    }
    public AnnulusArrayQueue1(Integer maxSize){
        this.maxSize = maxSize;
        employeeQueue = new Employee[this.maxSize];
    }

    /**
     *  Add a data, add it to the tail, add it to return true successfully, and return false failed
     */
    public boolean addEmployee(Employee employee){
        if(this.isFull()){
            return false;
        }
        this.employeeQueue[this.rear] = employee;
        this.rear = (this.rear+1)%this.maxSize;
        return true;
    }

    /*
     *  Get the first data and remove it from the queue
     */
    public Employee getEmployee(){
        if(isEmpty()){
            return null;
        }
        Employee employee = this.employeeQueue[this.front];
        this.front = (this.front+1)%this.maxSize;
        return employee;
    }

    /**
     *  Display the first data, only display, not remove from the queue
     */
    public Employee showEmployee(){
        if(isEmpty()){
            return null;
        }
        Employee employee = this.employeeQueue[this.front];
        return employee;
    }

    /**
     * Is the queue empty?
     */
    public boolean isEmpty(){
        return this.rear == this.front;
    }

    /**
     *  Is the queue full?
     */
    public boolean isFull(){
        return (this.rear+1)%this.maxSize == this.front;
    }
    /**
     * Format all the data of the queue
     */
    public String formatQueue(){
        if(isEmpty()){
            return "[]";
        }
        String str = "";
        for (int i = this.front;i<this.front+(this.rear + this.maxSize - this.front)%this.maxSize ;i++){
            str += employeeQueue[i%this.maxSize]+"\n";
        }
        return str;
    }
}

Advantage:

  • Solves the problem that space can not be reused after removing data

Disadvantages:

  • Queues contain limited amounts of data
  • A location will be vacated, that is, when the maximum queue capacity is 6, only 5 data can actually be inserted.

The second way is to achieve: Front and rear are no longer restricted by maxSize, but only when front and rear are used, find their actual position in the array by maxSize

The following information can be obtained from the above four situations:

  • The initial value front=rear=-1
  • front always points to the previous location of the first data, and rear always points to the last data.
  • The condition for judging the queue to be empty is front==rear
  • The condition for judging queue full is rear-front=maxSize
  • The number of valid data is rear-front
  • When entering the queue, add rear first, and then insert data at rear.
  • Add front before you leave the team, and then take out the data from front.
public class AnnulusArrayQueue2 {
    private Integer maxSize = 3;    //Maximum number of objects that can be accommodated in a queue
    private Integer front = -1;  //Always point before the first data
    private Integer rear = -1;  //Always point to the last data
    private Employee[] employeeQueue;   //Array for storing data
    public AnnulusArrayQueue2(){
        employeeQueue = new Employee[this.maxSize];
    }
    public AnnulusArrayQueue2(Integer maxSize){
        this.maxSize = maxSize;
        employeeQueue = new Employee[this.maxSize];
    }

    /**
     *  Add a data, add it to the tail, add it to return true successfully, and return false failed
     */
    public boolean addEmployee(Employee employee){
        if(this.isFull()){
            return false;
        }
        this.rear++;
        this.employeeQueue[this.rear%this.maxSize] = employee;
        return true;
    }

    /*
     *  Get the first data and remove it from the queue
     */
    public Employee getEmployee(){
        if(isEmpty()){
            return null;
        }
        this.front++;
        return this.employeeQueue[this.front%this.maxSize];
    }

    /**
     *  Display the first data, only display, not remove from the queue
     */
    public Employee showEmployee(){
        if(isEmpty()){
            return null;
        }
        Employee employee = this.employeeQueue[(this.front+1)%this.maxSize];
        return employee;
    }

    /**
     * Is the queue empty?
     */
    public boolean isEmpty(){
        return this.rear == this.front;
    }

    /**
     *  Is the queue full?
     */
    public boolean isFull(){
        return this.rear-this.front==this.maxSize;
    }
    /**
     * Format all the data of the queue
     */
    public String formatQueue(){
        if(isEmpty()){
            return "[]";
        }
        String str = "";
        for (int i = this.front+1;i<=this.rear ;i++){
            str += employeeQueue[i%this.maxSize]+"\n";
        }
        return str;
    }
}

Advantage:

  • Solves the problem that space can not be reused after removing data
  • Solve the problem that queues will have free positions

Disadvantages:

  • Queues contain limited amounts of data

Linked list implementation queue

Several cases of linked list queuing:

The following information can be obtained from the above four situations:

  • Initial value last=head
  • next of head points to the first data and last points directly to the last data.
  • The condition for judging the queue to be empty is head.next==null
  • The number of valid data is length
  • When entering the team, point last.next to the new data, and then last to the new data
  • Save head.next before leaving the queue, and then point head.next to the next of the extracted data.
public class LinkQueue {

    public int length = 0;  //Statistical Number of Data in Effective Queue
    private Node head;  //Head of queue
    private Node last;  //The tail of the queue

    public LinkQueue(){
        head = new Node();
        this.last = this.head;
    }

    /**
     *  Add a data, add it to the tail, add it to return true successfully, and return false failed
     */
    public boolean addEmployee(Employee employee){
        Node node = new Node();
        node.data = employee;
        this.last.next = node;
        this.last = node;
        this.length ++;
        return true;
    }

    /*
     *  Get the first data and remove it from the queue
     */
    public Employee getEmployee(){
        if(isEmpty()){
            return null;
        }
        Node temp = this.head.next;
        this.head.next = temp.next;
        length --;
        return temp.data;
    }

    /**
     *  Display the first data, only display, not remove from the queue
     */
    public Employee showEmployee(){
        if(isEmpty()){
            return null;
        }
        Node temp = this.head.next;
        return temp.data;
    }

    /**
     * Is the queue empty?
     */
    public boolean isEmpty(){
        return this.head.next == null;
    }

    /**
     * Format all the data of the queue
     */
    public String formatQueue(){
        if(isEmpty()){
            return "[]";
        }
        String str = "";
        Node temp = this.head.next;
        while (true){
            str += temp.data.toString() + "\n";
            if(temp.next==null){
                break;
            }
            temp = temp.next;
        }
        return str;
    }
    class Node{
        private Employee data;
        private Node next;
    }
}

Advantage:

  • Queue capacity unrestricted
  • There will be no empty positions in the queue
  • By using JVM garbage collection mechanism, system resources can be rationally utilized.

Topics: Programming Java IntelliJ IDEA JDK github