Este artigo detalha a implementação de operações básicas para uma fila circular utilizando a linguagme C. O objetivo é criar uma estrutura de dados de fila que utilize um array de tamanho fixo de forma eficiente, permitindo operações como inserção (enqueue), remoção (dequeue), obtenção do elemento do topo, cálculo do tamanho e travessia da fila.
A estrutura SqQueue é defniida para representar a fila circular, contendo um ponteiro para o array alocado dinamicamente (base), um índice para o elemento da frente (front) e um índice para a posição logo após o último elemento (rear).
#include <malloc.h>
#include <stdio.h>
#define OK 1
#define ERROR 0
typedef int Status; // Tipo para status de operações
typedef int QElemType; // Tipo dos elementos na fila
#define MAXQSIZE 100 // Tamanho máximo da fila (o espaço real utilizável é MAXQSIZE - 1)
typedef struct
{
QElemType *base; // Ponteiro para o início do array alocado
int front; // Índice do elemento da frente da fila
int rear; // Índice da posição do próximo elemento a ser inserido
}SqQueue;
Iincialização da Fila
A função InitQueue aloca memória para o array da fila e inicializa os ponteiros front e rear para zero, indicando uma fila vazia.
Status InitQueue(SqQueue &Q)
{
// Aloca memória para o array da fila com tamanho MAXQSIZE
Q.base = (QElemType*)malloc(sizeof(QElemType) * MAXQSIZE);
if (!Q.base) return ERROR; // Falha na alocação de memória
Q.front = 0; // Inicializa o ponteiro da frente
Q.rear = 0; // Inicializa o ponteiro do fim
return OK; // Operação bem-sucedida
}
Inserção na Fila (Enqueue)
A função EnQueue insere um elemento no final da fila. Ela verifica se a fila está cheia antes de realizar a inserção. A condição de fila cheia em uma fila circular é quando o próximo local do rear é igual ao front.
Status EnQueue(SqQueue &Q, QElemType e)
{
// Verifica se a fila está cheia
if ((Q.rear + 1) % MAXQSIZE == Q.front) return ERROR; // Fila cheia
else
{
Q.base[Q.rear] = e; // Insere o elemento na posição do rear
Q.rear = (Q.rear + 1) % MAXQSIZE; // Atualiza o ponteiro rear
}
return OK; // Operação bem-sucedida
}
Remoção da Fila (Dequeue)
A função DeQueue remove o elemento da frente da fila. Ela retorna o elemento removido através de uma referência e verifica se a fila está vazia antes da remoção. A condição de fila vazia é quando front é igual a rear.
Status DeQueue(SqQueue &Q, QElemType &e)
{
// Verifica se a fila está vazia
if (Q.front == Q.rear) return ERROR; // Fila vazia
else
{
e = Q.base[Q.front]; // Obtém o elemento da frente
Q.front = (Q.front + 1) % MAXQSIZE; // Atualiza o ponteiro front
}
return OK; // Operação bem-sucedida
}
Obter Elemento da Frente (GetHead)
A função GetHead retorna o elemento da frente da fila sem removê-lo. Ela verifica se a fila está vazia.
Status GetHead(SqQueue Q, QElemType &e)
{
// Verifica se a fila está vazia
if (Q.front == Q.rear) return ERROR; // Fila vazia
else
{
e = Q.base[Q.front]; // Obtém o elemento da frente
}
return OK; // Operação bem-sucedida
}
Comprimento da Fila (QueueLength)
A função QueueLength calcula e retorna o número de elementos presentes na fila.
int QueueLength(SqQueue Q)
{
// Calcula o número de elementos na fila
return (Q.rear - Q.front + MAXQSIZE) % MAXQSIZE;
}
Travessia da Fila (QueueTraverse)
A função QueueTraverse percorre a fila do início ao fim, imprimindo cada elemento. Ela verifica se a fila está vazia antes de iniciar a travessia.
Status QueueTraverse(SqQueue Q)
{
int i;
i = Q.front;
if (Q.front == Q.rear) {
printf("The Queue is Empty!\n"); // Fila vazia
} else {
printf("The Queue is: ");
while (i != Q.rear) { // Percorre até o ponteiro rear
printf("%d ", Q.base[i]); // Imprime o elemento atual
i = (i + 1) % MAXQSIZE; // Move para o próximo elemento ciclicamente
}
printf("\n");
}
return OK;
}
Função Principal (main)
A função main demonstra o uso das operações da fila circular. Ela inicializa a fila e, em seguida, entra em um loop que exibe um menu para o usuário interagir com a fila, permitindo inserir, remover, obter o topo, verificar o tamanho e exibir os elementos da fila, ou sair do programa.
int main()
{
int a;
SqQueue S;
QElemType x, e;
if (InitQueue(S)) { // Tenta inicializar a fila
printf("A Queue Has Created.\n");
}
while (1) {
printf("1:Enter \n2:Delete \n3:Get the Front \n4:Return the Length of the Queue\n5:Load the Queue\n0:Exit\nPlease choose:\n");
scanf("%d", &a);
switch (a) {
case 1: // Inserir elemento
scanf("%d", &x);
if (EnQueue(S, x) == ERROR) {
printf("Enter Error!\n"); // Erro ao inserir
} else {
printf("The Element %d is Successfully Entered!\n", x);
}
break;
case 2: // Remover elemento
if (DeQueue(S, e) == ERROR) {
printf("Delete Error!\n"); // Erro ao remover
} else {
printf("The Element %d is Successfully Deleted!\n", e);
}
break;
case 3: // Obter elemento da frente
if (GetHead(S, e) == ERROR) {
printf("Get Head Error!\n"); // Erro ao obter o topo
} else {
printf("The Head of the Queue is %d!\n", e);
}
break;
case 4: // Obter tamanho da fila
printf("The Length of the Queue is %d!\n", QueueLength(S));
break;
case 5: // Percorrer e exibir a fila
QueueTraverse(S);
break;
case 0: // Sair do programa
return 1;
}
}
return 0;
}