Estrutura de dados e algoritmo
2. Fila
Fila é uma lista ordenada que pode ser implementada com uma matriz ou uma lista vinculada.
Siga o princípio do primeiro a entrar, primeiro a sair.
Ideias de implementação (fila comum)
- Ao usar a estrutura de uma matriz para implementar uma fila, crie uma classe que contenha uma fila de objetos de matriz e, ao mesmo tempo, maxSize é necessário para indicar a capacidade máxima da fila;
- Como a entrada e a saída da fila são processadas separadamente da parte frontal e posterior, duas variáveis frontais e traseiras são necessárias para registrar os subscritos das extremidades frontal e posterior da fila, respectivamente. A frente mudará com a saída de dados e a parte traseira mudará com a entrada de dados;
- Entre eles, frente aponta para a posição anterior do primeiro objeto na fila .
- a retaguarda aponta para o fim da fila.
- O método addQueue na classe de escrita indica que a fila foi adicionada:
- Mova o ponteiro da cauda para trás para trás: traseiro + 1; quando dianteiro == traseiro (a fila está vazia).
- Se o ponteiro da cauda movido for menor que o subscrito máximo maxSize-1 da fila (o subscrito começa em 0), os dados são armazenados no elemento da matriz apontado por trás, caso contrário, os dados não podem ser armazenados (retaguarda == maxSeize-1, a fila está cheia )
- O método removeQueue na classe de escrita significa remover a fila:
- Quando a fila não estiver vazia, mova o ponteiro principal uma posição para a frente para encontrar o primeiro número na fila.
Implementação de código (fila normal)
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];
}
}
Problema: O ponteiro continua aumentando e a matriz não pode ser usada depois de usada, e o efeito de reutilização não é alcançado.
Solução: Mude a matriz para uma matriz circular e use o módulo para alcançar
Ideias de implementação (fila circular)
- O significado da variável front é ajustado, front aponta para o primeiro elemento da fila, arr [front] é o primeiro elemento da fila e o valor inicial de front é 0
- O conteúdo da variável traseira é ajustado, traseira aponta para a última posição do último elemento da fila, porque espera-se que um espaço seja deixado por convenção. Neste momento, a capacidade máxima utilizável da fila é maxSize-1, e o valor inicial de rear é 0;
- Quando a fila está cheia, a condição é (traseiro + 1)% maxSize == frente
- Quando a fila está vazia, traseira == frente
- O número de dados válidos na fila é (traseiro + maxSize -frotn)% maxSize
Implementação de código (fila circular)
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];
}
}
A classe de fila Queue em JAVA
Nos tipos de dados avançados de Java, a classe LinkedList implementa a interface Queue, para que possamos usar LinkedList como uma Fila.
LinkedList complementará a análise do código-fonte no capítulo sobre estrutura de dados de lista duplamente vinculada.
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);
}
}
}
A diferença entre oferecer e adicionar:
- Algumas filas têm limites de tamanho, portanto, se você quiser adicionar um novo item a uma fila cheia, o item extra será rejeitado.
- Neste momento, o novo método de oferta pode funcionar. Ele não lança uma exceção não verificada para chamar o método add (), mas apenas obtém o falso retornado por offer ().
A diferença entre poll e remove: - Os métodos remove () e poll () removem o primeiro elemento da fila. O comportamento de remove () é semelhante à versão da interface Collection, mas o novo método poll () não lança uma exceção quando chamado com uma coleção vazia, mas retorna null. Portanto, o novo método é mais adequado para situações propensas a condições anormais.
A diferença entre peek e element: - element () e peek () são usados para consultar os elementos no início da fila. Semelhante ao método remove (), quando a fila está vazia, element () lança uma exceção e peek () retorna null.