Structure de données JAVA-2. Implémentation de files d'attente ordinaires et de files d'attente circulaires et analyse de l'utilisation de JAVA Queue

Structure des données et algorithme

2. File d'attente

La file d'attente est une liste ordonnée, qui peut être implémentée avec un tableau ou une liste liée.

Suivez le principe du premier entré, premier sorti.

Insérez la description de l'image ici

Idées de mise en œuvre (file d'attente ordinaire)

  1. Lorsque vous utilisez la structure d'un tableau pour implémenter une file d'attente, créez une classe qui contient une file d'attente d'objets de tableau, et en même temps, maxSize est requis pour indiquer la capacité maximale de la file d'attente;
  2. Étant donné que l'entrée et la sortie de la file d'attente sont traitées séparément des extrémités avant et arrière, deux variables avant et arrière sont nécessaires pour enregistrer respectivement les indices des extrémités avant et arrière de la file d'attente. L'avant changera avec la sortie de données et l'arrière changera avec l'entrée de données.
    1. Parmi eux, front pointe vers la position précédente du premier objet de la file d'attente .
    2. l'arrière pointe vers la fin de la file d'attente.
  3. La méthode addQueue dans la classe d'écriture indique que la file d'attente est ajoutée:
    1. Déplacez le pointeur arrière vers l'arrière: arrière + 1; lorsque l'avant == arrière (la file d'attente est vide).
    2. Si le pointeur de queue déplacé est inférieur à l'indice maximum maxSize-1 de la file d'attente (l'indice commence à 0), les données sont stockées dans l'élément du tableau pointé par l'arrière, sinon les données ne peuvent pas être stockées (arrière == maxSeize-1, la file d'attente est pleine )
  4. La méthode removeQueue dans la classe d'écriture signifie supprimer la file d'attente:
    1. Lorsque la file d'attente n'est pas vide, déplacez le pointeur de tête d'une position pour trouver le premier numéro de la file d'attente.

Implémentation du code (file d'attente normale)

public class ArrayQueue {
    
    
    public  static void main(String args[]){
    
    
    }
}

class ArrayQueueClass{
    
    
    private int maxSize;
    private int front;
    private int rear;
    private int[] arr;
    public ArrayQueueClass(int arrMaxSize){
    
    
        this.maxSize = arrMaxSize;
        front = -1;
        rear = -1;
        arr = new int[arrMaxSize];
    }

    public boolean isEmpty(){
    
    
        if(front == rear){
    
    
            return true;
        }
        return false;
    }

    public boolean isFull(){
    
    
        if(rear == maxSize-1){
    
    
            return true;
        }
        return false;
    }

    public void addQueue(int data){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已经满了~");
        }
        rear++;
        arr[rear] = data;
    }

    public int removeQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空,无法取数据");
        }
        front++;
        return arr[front];
    }
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        for (int i = front+1; i <= rear ; i++) {
    
    
            System.out.printf("%d\t",arr[i]);
        }
        System.out.println();
    }

    public int check(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }

        return arr[front+1];
    }

}

Problème: le pointeur continue d'augmenter et le tableau ne peut pas être utilisé une fois qu'il est utilisé, et l'effet de réutilisation n'est pas obtenu.

Solution: changez le tableau en un tableau circulaire et utilisez modulo pour obtenir

Idées de mise en œuvre (file d'attente circulaire)

  1. La signification de la variable front est ajustée, front pointe vers le premier élément de la file d'attente, arr [front] est le premier élément de la file d'attente et la valeur initiale de front est 0
  2. Le contenu de la variable arrière est ajusté, l'arrière pointe vers la dernière position du dernier élément de la file d'attente, car on espère qu'un espace est laissé comme convention. À ce stade, la capacité maximale utilisable de la file d'attente est maxSize-1 et la valeur initiale de l'arrière est 0;
  3. Lorsque la file d'attente est pleine, la condition est (arrière + 1)% maxSize == front
  4. Lorsque la file d'attente est vide, arrière == avant
  5. Le nombre de données valides dans la file d'attente est (Rear + maxSize -frotn)% maxSize

Implémentation de code (file d'attente circulaire)

public class CircleArrayQueueDemo {
    
    
    public  static void main(String args[]){
    
    
        CricleArrayQueue queue = new CricleArrayQueue(4);   //此时可以用队列为3
        queue.addQueue(0);
        queue.showQueue();
        queue.addQueue(1);
        queue.showQueue();
        queue.addQueue(2);
        queue.showQueue();
//        queue.addQueue(3); //java.lang.RuntimeException: 队列已经满了~  front==0  rear==3

        System.out.println(queue.removeQueue());
        queue.showQueue();
        System.out.println(queue.removeQueue());
        queue.showQueue();
        System.out.println(queue.removeQueue());
        System.out.println();
//        queue.showQueue();//java.lang.RuntimeException: 队列为空  front == rear ==3

        queue.addQueue(4);  //front ==3  rear ==0
        queue.showQueue();
        queue.addQueue(5); //front ==3  rear ==1

        System.out.println(queue.removeQueue());//front ==0  rear ==1
        System.out.println(queue.removeQueue());//front ==1  rear ==1

    }
}
class CricleArrayQueue{
    
    
    private int maxSize;
    public int front;
    public int rear;
    private int[] arr;
    public CricleArrayQueue(int arrMaxSize){
    
    
        this.maxSize = arrMaxSize;
        front = 0;  //front表示指向第一个元素 取元素时先取再+1
        rear = 0;   //rear表示指向最后一个元素的后一个位置  加元素时先加元素在+1
        arr = new int[arrMaxSize];  //设置队列最大长度,此时保留一个位置作为队列满的判断,因此最大可用数量为maxSize-1
    }
    public boolean isEmpty(){
    
    
        if(front == rear){
    
    
            return true;
        }
        return false;
    }

    public boolean isFull(){
    
    
        if((rear+1)%maxSize == front){
    
    
            return true;
        }
        return false;
    }
    public void addQueue(int data){
    
    
        if(isFull()){
    
    
            throw new RuntimeException("队列已经满了~");
        }
        arr[rear] = data;
        rear = (rear+1)%maxSize;
    }
    public int removeQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空,无法取数据");
        }
        int value = arr[front];
        front = (front+1)%maxSize;
        return value;
    }
    public void showQueue(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        for (int i = front; i < front+ (rear - front + maxSize)%maxSize; i++) {
    
    
            System.out.printf("%d\tarr[%d]",i%maxSize,arr[i%maxSize]);
            System.out.println();
        }
        System.out.println();
    }
    public int check(){
    
    
        if(isEmpty()){
    
    
            throw  new RuntimeException("队列为空");
        }
        return arr[front];
    }

}

La classe de file d'attente Queue dans JAVA

Dans les types de données avancés de Java, la classe LinkedList implémente l'interface Queue, afin que nous puissions utiliser LinkedList comme file d'attente.
LinkedList complétera l'analyse du code source dans le chapitre sur la structure de données de liste à double liaison.

public class javaQueue {
    
    
    public  static void main(String args[]){
    
    
        //add()和remove()方法在失败的时候会抛出异常(不推荐)
        Queue<String> queue = new LinkedList<String>();
        //添加元素
        queue.offer("a");
        queue.offer("b");
        queue.offer("c");
        queue.offer("d");
        queue.offer("e");
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("poll="+queue.poll()); //返回第一个元素,并在队列中删除
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("element="+queue.element()); //返回第一个元素
        for(String q : queue){
    
    
            System.out.println(q);
        }
        System.out.println("===");
        System.out.println("peek="+queue.peek()); //返回第一个元素
        for(String q : queue){
    
    
            System.out.println(q);
        }
    }
}

La différence entre l'offre et l'ajout:

  • Certaines files d'attente ont des limites de taille, donc si vous souhaitez ajouter un nouvel élément à une file d'attente complète, l'élément supplémentaire sera rejeté.
  • À ce stade, la nouvelle méthode d'offre peut fonctionner. Il ne lève pas d'exception non vérifiée pour appeler la méthode add (), mais récupère simplement le false renvoyé par offer ().
    La différence entre poll et remove:
  • Les méthodes remove () et poll () suppriment le premier élément de la file d'attente. Le comportement de remove () est similaire à la version de l'interface Collection, mais la méthode new poll () ne lève pas d'exception lorsqu'elle est appelée avec une collection vide, mais renvoie null. Par conséquent, la nouvelle méthode est plus adaptée aux situations sujettes à des conditions anormales.
    La différence entre peek et element:
  • element () et peek () sont utilisés pour interroger des éléments en tête de file d'attente. Similaire à la méthode remove (), lorsque la file d'attente est vide, element () lève une exception et peek () renvoie null.

Je suppose que tu aimes

Origine blog.csdn.net/weixin_44634197/article/details/108308221
conseillé
Classement