Search code examples
calgorithmdata-structuresqueue

Queue Data Structure in C


/*
    * File name: a15f3.c
    ------------------
*/

#include <stdio.h>

#define QueueLimit 11

typedef int QueueElementType;
                                  
typedef struct {
    int Front, Rear;
    int Count;
    QueueElementType Element[QueueLimit];
} QueueType;

typedef enum { FALSE, TRUE } boolean;

void CreateQ(QueueType* Queue);
boolean EmptyQ(QueueType Queue);
boolean FullQ(QueueType Queue);
void RemoveQ(QueueType* Queue, QueueElementType* Item);
void AddQ(QueueType* Queue, QueueElementType Item);
void TraverseQ(QueueType Queue);

int main() {
    //Variable declaration
    QueueType Q;
    QueueElementType Item;
    int i, num;

    CreateQ(&Q);
    for (i = 3; i <= 30; i += 3)
        AddQ(&Q, i);

    printf("(a)\n");
    TraverseQ(Q);

    printf("(b)\n");
    do {
        printf("Give a number:");
        scanf("%d", &num);
        if ((num % 3) != 0)
            printf("Give a multiple of 3\n");
    } while ((num % 3) != 0);
    AddQ(&Q, num);
    TraverseQ(Q);

    printf("(c)\n");
    RemoveQ(&Q, &Item);
    TraverseQ(Q);
    printf("Removed item=%d\n", Item);

    printf("(d)\n");
    for (i = 0; i < 2; i++) {
        do {
            printf("Give a number:");
            scanf("%d", &num);
            if ((num % 3) != 0)
                printf("Give a multiple of 3\n");
        } while ((num % 3) != 0);
        AddQ(&Q, num);
        TraverseQ(Q);
    }

    printf("(e)\n");
    while(!EmptyQ(Q)) {
        RemoveQ(&Q, &Item);
        TraverseQ(Q);
        printf("Removed item=%d\n", Item);
    }

    return 0;
}
void CreateQ(QueueType* Queue) {
    Queue->Front = 0;
    Queue->Rear = 0;
    Queue->Count = 0;
}

boolean EmptyQ(QueueType Queue) {
    return (Queue.Count == 0);
}

boolean FullQ(QueueType Queue) {
    return (Queue.Count == (QueueLimit - 1));
}

void RemoveQ(QueueType* Queue, QueueElementType* Item) {
    if (!EmptyQ(*Queue))
    {
        *Item = Queue->Element[Queue->Front];
        Queue->Front = (Queue->Front + 1) % (QueueLimit - 1);
        Queue->Count--;
    }
    else
        printf("Empty Queue\n");
}

void AddQ(QueueType* Queue, QueueElementType Item) {
    if (!FullQ(*Queue))
    {
        Queue->Element[Queue->Rear] = Item;
        Queue->Rear = (Queue->Rear + 1) % (QueueLimit - 1);
        Queue->Count++;
    }
    else
        printf("Full Queue\n");
}

void TraverseQ(QueueType Queue) {
    int current;

    printf("Queue: ");

    if (!EmptyQ(Queue)) {
        current = Queue.Front;
        while (current != Queue.Count) {
            printf("%d ", Queue.Element[current]);
            current = (current + 1) % QueueLimit;
        }
        printf("\n");
        printf("Front=%d Rear=%d Count=%d\n", Queue.Front, Queue.Rear, Queue.Count);
    }
    else printf("Empty Queue\n");
}

I have a problem. I want to add some multiples of 3 in the queue, print them and then remove the elements one by one. Although the elements are stored correctly in their positions in the queue, there is a problem with the Traverse of the queue. If you notice the last element of the queue, when 3 is removed it cannot be showed in the screen for all the removements. Can somebody help me?

The expected result is the following:

enter image description here enter image description here


Solution

  • Some issues and remarks:

    • The loop condition for iterating the values is not correct. Either you should have a counter that starts at 0 and continues until Q->Count or you should compare current with Q->Rear.

    • Since the size of the queue is QueueLimit, your modulo arithmetic should be modulo QueueLimit, not QueueLimit-1. Similarly, the queue is only full when Queue.Count == QueueLimit, not Queue.Count == QueueLimit - 1.

    • As Q->Rear can be derived from Q->Front and Q->Count I would actually not store that functionaly dependent property.

    • You could have RemoveQ and AddQ return a boolean indicating whether the operation succeeded.

    typedef struct {
        int Front; // No rear
        int Count;
        QueueElementType Element[QueueLimit];
    } QueueType;
    
    void CreateQ(QueueType* Queue) {
        Queue->Front = 0;
        Queue->Count = 0;
    }
    
    boolean EmptyQ(QueueType Queue) {
        return Queue.Count == 0;
    }
    
    boolean FullQ(QueueType Queue) {
        return Queue.Count == QueueLimit; // corrected
    }
    
    boolean RemoveQ(QueueType* Queue, QueueElementType* Item) {
        if (!EmptyQ(*Queue)) {
            *Item = Queue->Element[Queue->Front];
            Queue->Front = (Queue->Front + 1) % QueueLimit; // corrected
            Queue->Count--;
            return 1;
        }
        printf("Nothing to remove\n");
        return 0;
    }
    
    boolean AddQ(QueueType* Queue, QueueElementType Item) {
        if (!FullQ(*Queue)) {
            Queue->Element[(Queue->Front + Queue->Count) % QueueLimit] = Item;
            Queue->Count++;
            return 1;
        }
        printf("Full Queue\n");
        return 0;
    }
    
    void TraverseQ(QueueType Queue) {
        printf("Queue (Front=%d Count=%d):\n", Queue.Front, Queue.Count);
        for (int i = 0; i < Queue.Count; i++) { // Number of iterations must be Count
            printf("%d ", Queue.Element[(Queue.Front + i) % QueueLimit]); 
        }
        printf(EmptyQ(Queue) ? "Empty Queue\n" : "\n");
    }