"Data structure and algorithm described in language analysis --C" to achieve the ADT (NO.02): a queue (Queue)

The third structure - a queue (Queue)

In contrast with the last queue stack, a first in first out (FIFO) linear form. Only the tail exposed when writing, only the head exposed when reading.

 

The only implements an array of queues. The reason is very simple linked list of queues, just simple delete the first node and the tail insert two operations, this will no longer be in the implementation.

For an array of queues, the memory unit is fixed, as the stack do not have the characteristics as a fixed end, that the space for the array can be reused as required so that the head of the queue moves Dequeue operation. If the entire contents of each Dequeue will forward a queue unit that is a O (n) complexity of the operation, in terms of cost for deletion is too large. Therefore, we do not move the element itself, but to indicate the head of the queue (Front) and tail (Rear) identified by two, as Dequeue operation, move backwards Front. As a result, the empty space in front of it, when the tail reaches the end of the array, the array back using the head space. I.e. form a loop array.

At this point, we can know by the size relationship between the Front and Rear queue length, whether it is full, it is empty.

 

Of particular note is that , once the cycle, we imagine when Front is determined, a total of how many different lengths of queues can form?

Obviously, the number of values can be taken Rear length of the array (referred to as m) are equal. That is, the corresponding queue length may be 0, 1, 2, 3, ..., m-1. This is the problem, an array of length m, the queue after the cyclic structure formed can be represented by the maximum length of is m-1.

We may wish to think about why. In fact, if we use an array of length m, m represents the maximum length of the queue, if:

  (I) Front indicating a position of the first element, Rear indicating the position of the last element. So we can not represent the situation empty queue.

  (II) Front indicating position before the first element (similar to the first node in the linked list, the actual data is not saved), it indicates an empty queue when the Front and Rear coincide, then m can not be represented as a queue length. Because no matter what the position is in the Front, no matter how much the queue length, there is always a position that does not save the data. Rear position after the last element indicates the same as described above, it is no longer single (iii).

Thus, to create the maximum queue length n, you need to apply (n + 1) * sizeof (ElementType) array space. Down seemingly nonsense to say so, it seems very easy can think of, but in fact not very familiar with the queue, the queue is likely to achieve the preparation ignore this.

As before the empty cell in the first concrete element (Front indicated) or after the last element (Rear indicated), no significant impact. The following implementation, the author uses the former embodiment.

The code is given below

// Queue.h

#include <stdio.h>
#include <stdlib.h>

struct QueueRecord;
typedef struct QueueRecord *Queue;

int IsEmpty(Queue Q);
int IsFull(Queue Q);
Queue CreateQueue(int MaxElements);
void DisposeQueue(Queue Q);
void MakeEmpty(Queue Q);
void Enqueue(ElementType X, Queue Q);
ElementType Front(Queue Q);
void Dequeue(Queue Q);
ElementType FrontAndDequeue(Queue Q);

  

// Queue.c

#include "Queue.h"

struct QueueRecord{
    int Capacity;
    int Front;
    int Rear;
    int Size;
    ElementType *Array;
};


int IsEmpty(Queue Q)
{
    return Q->Size == 0;
}

int IsFull(Queue Q)
{
    return Q->Size == Q->Capacity;
}

Queue CreateQueue(int MaxElements)
{
    Queue ret;
    if((ret = (Queue)malloc(sizeof(struct QueueRecord))) == NULL)
    {
        printf("Error! Out of memory! \n");
        return NULL;
    }
    if((ret->Array = (ElementType*)malloc(sizeof(ElementType) * (1 + MaxElements))) == NULL)
    {
        printf("Error! Out of memory! \n");
        free(ret);
        return NULL;
    }
    ret->Capacity = MaxElements;
    ret->Size = 0;
    ret->Front = ret->Rear = 0;
    return ret;
}

void DisposeQueue(Queue Q)
{
    if(Q)
    {
        free(Q->Array);
        free(Q);
    }
}

void MakeEmpty(Queue Q)
{
    Q->Rear = Q->Front;
    Q->Size = 0;
}

void Enqueue(ElementType X, Queue Q)
{
    int t;
    if(IsFull(Q))
    {
        printf("Error! The queue is full! \n");
        return;
    }
    t = (Q->Rear + 1) % (Q->Capacity + 1);
    Q->Array[t] = X;
    Q->Rear = t;
    Q->Size += 1;
}

ElementType Front(Queue Q)
{
    if (IsEmpty(Q))
    {
        printf("Error! The queue is empty! \n");
        return 0;
    }
    return (Q->Array)[Q->Front];
}

void Dequeue(Queue Q)
{
    if (IsEmpty(Q))
    {
        printf("Error! The queue is empty! \n");
        return;
    }
    Q->Front = (Q->Front + 1) % (Q->Capacity + 1);
    Q->Size -= 1;
}

ElementType FrontAndDequeue(Queue Q)
{
    ElementType ret;
    if (IsEmpty(Q))
    {
        printf("Error! The queue is empty! \n");
        return 0;
    }
    ret = (Q->Array)[Q->Front];
    Q->Front = (Q->Front + 1) % (Q->Capacity + 1);
    Q->Size -= 1;
    return ret;
}

  

Guess you like

Origin www.cnblogs.com/DrChuan/p/11280034.html