Imagine que você está em um banco. Quem chega primeiro é atendido primeiro, seguindo o princípio básico de uma fila comum, conhecido como FIFO (First In, First Out). No entanto, há situações em que algumas pessoas têm prioridade, como idosos ou gestantes, que são atendidas antes, independentemente da ordem de chegada. Em programação, esse conceito é representado pelas filas normais e filas prioritárias.
Neste artigo exploraremos esses dois tipos de filas e seus conceitos, aplicações práticas e como implementá-los em C#.
Aplicação do conceito de filas
Filas são amplamente utilizadas em diversas situações, como:
- Gerenciamento de tarefas: você pode usar filas para garantir que as tarefas sejam processadas na ordem em que foram recebidas.
- Simulações de processos reais: como filas de espera, onde os clientes são atendidos conforme sua ordem de chegada.
- Armazenamento temporário de dados: quando você precisa armazenar dados enquanto espera que sejam processados assincronamente.
- Algoritmos de busca: Como a busca em largura (BFS), que explora elementos em uma ordem específica.
A classe Queue no .NET
No .NET, a classe “Queue<T>” é uma implementação de fila genérica que fornece métodos simples para manipulação de dados em uma fila. Ela oferece eficiência e facilidade de uso.
Principais métodos da classe Queue<T>
- Enqueue(T item): adiciona um item ao final da fila.
- Dequeue(): remove e retorna o item no início da fila. Se a fila estiver vazia, uma exceção será lançada.
- Peek(): retorna o item no início da fila sem removê-lo, mas lança uma exceção se a fila estiver vazia.
- Count: retorna o número total de itens na fila.
- Clear(): remove todos os itens da fila.
Agora vamos ver um exemplo de uso:
using System;
using System.Collections.Generic;
class Cliente
{
public string Nome { get; set; }
public int SenhaAtendimento { get; set; }
}
public class Program
{
public static void Main()
{
Queue fila = new Queue();
fila.Enqueue(new Cliente { Nome = "José Rodrigues", SenhaAtendimento = 101 });
fila.Enqueue(new Cliente { Nome = "Marcos Silva", SenhaAtendimento = 102 });
fila.Enqueue(new Cliente { Nome = "Ana Souza", SenhaAtendimento = 103 });
Console.WriteLine("\nProcessando a fila:");
while (fila.Count > 0)
{
Cliente proximoCliente = fila.Peek();
Console.WriteLine($"Próximo: {proximoCliente.Nome} (Senha: {proximoCliente.SenhaAtendimento})");
Cliente clienteAtual = fila.Dequeue();
Console.WriteLine($"Atendendo:{clienteAtual.Nome}(Senha: {clienteAtual.SenhaAtendimento})");
}
Console.WriteLine($"\nClientes restantes na fila: {fila.Count}");
}
}
No exemplo acima criamos uma fila (Queue<Cliente>) para armazenar objetos do tipo “Cliente”. Isso garante que apenas objetos desse tipo possam ser adicionados. Utilizamos o método “Enqueue” para inserir clientes na fila.
O loop while processa os clientes enquanto houver elementos na fila. Antes de atender um cliente, usamos “Peek” para obter uma prévia do próximo cliente na fila sem removê-lo. Isso simula um painel informando quem será o próximo a ser atendido.
Após isso, o método “Dequeue” remove o primeiro cliente da fila e retorna seu valor. Assim, o cliente é efetivamente atendido e retirado da fila. Após processar todos os clientes, exibimos a contagem restante usando “fila.Count”, que será igual a “0”.
Fila Prioritária (Priority Queue)
Diferentemente das filas tradicionais, nas quais os elementos são processados na ordem em que foram adicionados (FIFO), as filas prioritárias organizam os elementos com base em uma prioridade associada a cada item. O elemento com a maior prioridade é processado primeiro, independentemente da ordem de chegada.
Quando usar uma Fila Prioritária?
As filas prioritárias são úteis em diversas situações, como:
- Sistemas de saúde: para garantir que pacientes em estado grave sejam atendidos antes dos outros.
- Sistemas operacionais: no agendamento de processos, onde tarefas críticas têm precedência.
- Jogos: para gerenciar eventos em tempo real, priorizando os mais importantes.
A classe PriorityQueue no .NET
No .NET 6 foi introduzida a classe “PriorityQueue<TElement, TPriority>”, que oferece uma implementação eficiente e fácil de usar para filas prioritárias.
using System;
using System.Collections.Generic;
public class Program
{
public static void Main()
{
PriorityQueue filaPrioritaria = new PriorityQueue();
filaPrioritaria.Enqueue("Paciente Leve", 3);
filaPrioritaria.Enqueue("Paciente Moderado", 2);
filaPrioritaria.Enqueue("Paciente Grave", 1);
Console.WriteLine("Processando a fila prioritária:");
while (filaPrioritaria.Count > 0)
{
string proximoPaciente = filaPrioritaria.Peek();
Console.WriteLine($"Próximo a ser atendido: {proximoPaciente}");
string pacienteAtendido = filaPrioritaria.Dequeue();
Console.WriteLine($"Atendendo: {pacienteAtendido}");
}
Console.WriteLine("Todos os pacientes foram atendidos.");
}
}
Criamos uma fila prioritária de strings (PriorityQueue<string, int>) em que o nome do paciente é o elemento e sua prioridade é representada por um número inteiro. Os elementos com menor valor de prioridade (ex.: 1) têm precedência sobre os de maior valor. Usamos o método “Enqueue” para adicionar pacientes com suas respectivas prioridades.
Em seguida o loop while processa os pacientes, atendendo primeiro os de maior prioridade (menor valor de prioridade numérica). Por fim, exibimos o próximo paciente com “Peek” antes de removê-lo e atendê-lo com “Dequeue”.
Esse modelo é ideal para cenários que exigem um atendimento organizado por relevância ou urgência, como sistemas hospitalares ou gerenciamento de eventos críticos.
Acelere a sua carreira conosco!
Se você é Desenvolvedor .NET Júnior e quer acelerar sua carreira até nível Pleno com salário de R$7k+, ou mesmo busca a primeira vaga, conheça a Mentoria .NET Start: Clique aqui
Se é Desenvolvedor .NET Pleno ou Sênior e quer virar referência técnica em sua equipe e mercado, com salário de R$10k+, conheça a Mentoria .NET Expert: Clique aqui
Conclusão
As filas são estruturas de dados bastente utilizadas para resolver problemas que requerem ordenação e processamento sequencial ou baseado em prioridade. Com a classe “Queue<T>” e a “PriorityQueue<TElement, TPriority>”, você pode implementar soluções para cenários que vão desde a simulação de processos reais até o desenvolvimento de algoritmos eficientes.
Escolher o tipo correto de fila para cada caso de uso é fundamental para garantir a eficiência e a clareza do seu código.