Force buckle -- design cycle queue (problem solution)

Posted by trygve on Sat, 19 Feb 2022 01:32:12 +0100

This problem needs to implement a circular queue, so before that, we need to know the concept and structure of queue

Queue: a special linear table that can only be inserted at one end and deleted at the other end. It has the characteristics of first in first out, then in and then out
Delete one end of the queue
Enter the queue: the end of the insertion is called the end of the queue


Knowing the concept and structure of queue, you can start to do this problem.
Title Link
Title Description:

Idea: first, find the condition that the queue is empty and the condition that the queue is full. It is easy to find these two conditions. I give the condition that the queue is empty. When the head and tail of the queue are equal, it means that the queue is empty. If the queue is full, the queue will be full when it is equal to the next one at the end of the queue. Careful friends may have seen it here. In this case, don't you need one less data? It's true. But in order to solve this problem, I decided to use the last space of the queue as the end condition, but I don't want to lose one of the transmitted data, so I directly opened an additional space to judge the end when I created it, which perfectly solves the problem that there is a lot of data and can judge whether the queue is full

First, we need a circular queue structure. I define it as follows:

typedef struct {
    int* a;
    int k;//Total queue size
    int front;//Team leader
    int tail;//Team tail

} MyCircularQueue;

It looks like this:

Let's implement an initialization function MyCircularQueue* myCircularQueueCreate(int k);

MyCircularQueue* myCircularQueueCreate(int k) {
    //A queue
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //Initialize queue
    //One more space should be opened here to judge whether the queue is full
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    obj->front = 0;
    obj->tail = 0;
    obj->k = k;

    //Returns the address of the queue
    return obj;
}

After implementing the above function, we begin to implement a function bool mycircularqueue isempty (mycircularqueue * obj) to judge whether the queue is empty; And the function bool myCircularQueueIsFull(MyCircularQueue* obj) to judge whether the queue is full;

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    
    //If front and tail are equal, it means they are empty
    return obj->front == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {

    //The next coordinate of the tail of the team is given to tailNext;
    int tailNext = obj->tail + 1;

    //If it is equal to the coordinates of the last space, the queue is full at this time
    if (tailNext == obj->k + 1)
    {
        //Set it as the coordinates of the head
        tailNext = 0;
    }

    return tailNext == obj->front;
}

With these two functions, we can start to implement the queue insertion function

According to the above steps, we can quickly implement the insertion function

bool myCircularQueueEnQueue( MyCircularQueue* obj, int value) {

    //Judge whether it is full. If it is full, do not insert it
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        //Insert it into the tail position and increase it automatically
        obj->a[obj->tail] = value;
        obj->tail++;

        //It is used to prevent cross-border. When tail is greater than k, it is set to 0 to complete the circular queue
        obj->tail %= (obj->k + 1);

        return true;
    }
}

Since the delete function of the delete queue is similar to the insert function, I won't repeat it one by one here. I believe you understand the logic of the insert, and the deletion should be very simple.

All codes:

typedef struct {
    int* a;
    int k;//Total queue size
    int front;//Team leader
    int tail;//Team tail

} MyCircularQueue;


MyCircularQueue* myCircularQueueCreate(int k) {
    //A queue
    MyCircularQueue* obj = (MyCircularQueue*)malloc(sizeof(MyCircularQueue));
    //Initialize queue
    //One more space should be opened here to judge whether the queue is full
    obj->a = (int*)malloc(sizeof(int) * (k + 1));
    obj->front = 0;
    obj->tail = 0;
    obj->k = k;

    //Returns the address of the queue
    return obj;
}

bool myCircularQueueIsEmpty(MyCircularQueue* obj) {
    
    //If front and tail are equal, it means they are empty
    return obj->front == obj->tail;
}

bool myCircularQueueIsFull(MyCircularQueue* obj) {

    //The next coordinate of the tail of the team is given to tailNext;
    int tailNext = obj->tail + 1;

    //If it is equal to the coordinates of the last space, the queue is full at this time
    if (tailNext == obj->k + 1)
    {
        //Set it as the coordinates of the head
        tailNext = 0;
    }

    return tailNext == obj->front;
}

bool myCircularQueueEnQueue( MyCircularQueue* obj, int value) {

    //Judge whether it is full. If it is full, do not insert it
    if (myCircularQueueIsFull(obj))
    {
        return false;
    }
    else
    {
        //Insert it into the tail position and increase it automatically
        obj->a[obj->tail] = value;
        obj->tail++;

        //It is used to prevent cross-border. When tail is greater than k, it is set to 0 to complete the circular queue
        obj->tail %= (obj->k + 1);

        return true;
    }
}

bool myCircularQueueDeQueue(MyCircularQueue* obj) {
    
    if ( myCircularQueueIsEmpty(obj))
    {
        return false;
    }
    else
    {
        //Each self increment of header is equivalent to the data of one queue
        obj->front++;

        //It is used to prevent cross-border. When the front is greater than k, it is set to 0 to complete the circular queue
        obj->front %= (obj->k + 1);

        return true;
    }

}

int myCircularQueueFront(MyCircularQueue* obj) {

    //Judge whether it is empty. If it is empty, return - 1
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }
    else//If it is not empty, return the header data
    {
        return obj->a[obj->front];
    }
}

int myCircularQueueRear(MyCircularQueue* obj) {

    //If the queue is empty, - 1 is returned
    if (myCircularQueueIsEmpty(obj))
    {
        return -1;
    }

    //tail is the previous and the last data
    int tailPrev = obj->tail - 1;

    //If tailPrev is equal to - 1, the tail at this time is 0
    if (tailPrev == -1)
    {
        tailPrev = obj->k;
    }

    //Return the data of tailPrev
    return obj->a[tailPrev];
}

void myCircularQueueFree(MyCircularQueue* obj) {

    //Release queue
    free(obj->a);
    free(obj);

}

/**
 * Your MyCircularQueue struct will be instantiated and called as such:
 * MyCircularQueue* obj = myCircularQueueCreate(k);
 * bool param_1 = myCircularQueueEnQueue(obj, value);
 
 * bool param_2 = myCircularQueueDeQueue(obj);
 
 * int param_3 = myCircularQueueFront(obj);
 
 * int param_4 = myCircularQueueRear(obj);
 
 * bool param_5 = myCircularQueueIsEmpty(obj);
 
 * bool param_6 = myCircularQueueIsFull(obj);
 
 * myCircularQueueFree(obj);
*/

Topics: C C++ Algorithm data structure queue