基本数据结构 -- 队列(数组实现)

  队列是一种先进先出(FIFO)的线性表。对队列的基本操作有两种: 入队(Enqueue),在表的末端(队尾 tail)插入一个元素;出队(Dequeue),删除或返回在表的开头(队头 head)的元素。本文介绍如何使用数组在 C 语言中实现一个队列,平台为VS2010。

  先创建一个队列结构体,这个结构体应该包括这几个元素:队头在数组中的位置(Front)、队尾在数组中的位置(Rear)、队列的大小(Size)、用于存储队列的数组(Array)以及数组的容量(Capacity):

typedef int ElementType;

struct QueueRecord {
    int Capacity;          // 数组容量
    int Front;             // 队头的位置
    int Rear;              // 队尾的位置
    int Size;             // 队列大小
    ElementType *Array;    // 用于存放队列的数组
};

typedef struct QueueRecord Queue;
typedef struct QueueRecord *PtrToQueue;

 

一、创建队列

  使用前面的结构体来创建一个队列:

PtrToQueue CreateQueue(int capacity)
{
    PtrToQueue queue = (PtrToQueue )malloc(sizeof(Queue));
    if (queue == NULL) {
        perror("malloc failed!\n");
        exit(EXIT_FAILURE);
    }

    queue->Capacity = capacity;
    queue->Array = (ElementType *)malloc(sizeof(ElementType) * capacity);
    MakeEmpty(queue);

    return queue;
}


void MakeEmpty(PtrToQueue Q)
{
    Q->Size = 0;  // 队列长度设为1
    Q->Front = 1;  // 队头位置为 1
    Q->Rear = 0;    // 队尾位置为 0
}

 

二、入队操作

   向指定队列的尾部插入一个元素,即为入队操作。在每次插入之前都要判断队列是否还有空间供新元素插入。

void Enqueue(PtrToQueue Q,ElementType element)
{
    if (IsFull(Q)) {
        perror("队列已满,入队失败\n");
        exit(EXIT_FAILURE);
    }
    else {
        Q->Size++;    // 队列大小加 1
        if (++Q->Rear == Q->Capacity) {
            Q->Rear = 0;
        }
        Q->Array[Q->Rear] = element;
    }
}

bool IsFull(PtrToQueue Q)
{
    return Q->Size == Q->Capacity;
}

  在入队操作中,设置了一个循环数组,在队尾位置要超出数组边界时,将队尾放到数组开始处,以便最大利用数组空间。 

  

三、出队操作

   将队列的队头元素从队列中删除,对于数组队列,只需要将队头位置加 1 即可。

void Dequeue(PtrToQueue Q)
{
    if (IsEmpty(Q)) {
        perror("队列为空,无法执行出队操作\n");
        exit(EXIT_FAILURE);
    }
    else {
        Q->Size--;    // 队列大小减 1
        if (++Q->Front == Q->Capacity) {
            Q->Front = 0;
        }        
    }

}

bool IsEmpty(PtrToQueue Q)
{
    return Q->Size == 0;
}

  同样的,为了最大利用数组空间,出队操作也使用了循环数组。 

 

四、遍历队列

  从队头元素开始遍历整个队列:

void TraverseQueue(PtrToQueue Q)
{
    if (Q->Size == 0) {
        printf("队列为空\n");
    }

    for (int i = 0; i < Q->Size; i++) {
        if (Q->Front + i < Q->Capacity) {
            printf("%d ", Q->Array[Q->Front + i]);
        }
        else {
            printf("%d ", Q->Array[Q->Front + i - Q->Capacity]);
        }
        
    }
}

 

五、完整代码

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

typedef int ElementType;

struct QueueRecord {
    int Capacity;        // 数组容量
    int Front;            // 队头的位置
    int Rear;            // 队尾的位置
    int Size;            // 队列大小
    ElementType *Array;    // 用于存放队列的数组
};

typedef struct QueueRecord Queue;
typedef struct QueueRecord *PtrToQueue;

PtrToQueue CreateQueue(int capacity);
void MakeEmpty(PtrToQueue Q);
void Enqueue(PtrToQueue Q, ElementType element);
void Dequeue(PtrToQueue Q);
bool IsFull(PtrToQueue Q);
bool IsEmpty(PtrToQueue Q);
void TraverseQueue(PtrToQueue Q);
ElementType Peek(PtrToQueue Q);


int main()
{
    PtrToQueue newQueue = CreateQueue(10);    // 创建一个空队列
    for (int i = 0; i < 10; i++) {
        Enqueue(newQueue,i);            // 向队列中添加元素
    }
    
    TraverseQueue(newQueue);            // 遍历队列

    Dequeue(newQueue);                // 出队
    Dequeue(newQueue);                // 出队
    TraverseQueue(newQueue);

    Enqueue(newQueue, 50);             // 入队
    TraverseQueue(newQueue);

    return 0;
}

// 创建一个队列
PtrToQueue CreateQueue(int capacity)
{
    PtrToQueue queue = (PtrToQueue )malloc(sizeof(Queue));
    if (queue == NULL) {
        perror("malloc failed!\n");
        exit(EXIT_FAILURE);
    }

    queue->Capacity = capacity;
    queue->Array = (ElementType *)malloc(sizeof(ElementType) * capacity);
    MakeEmpty(queue);

    return queue;
}


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

// 入队
void Enqueue(PtrToQueue Q,ElementType element)
{
    if (IsFull(Q)) {
        perror("队列已满,入队失败\n");
        exit(EXIT_FAILURE);
    }
    else {
        Q->Size++;
        if (++Q->Rear == Q->Capacity) {
            Q->Rear = 0;
        }
        Q->Array[Q->Rear] = element;
        
    }
}

// 出队
void Dequeue(PtrToQueue Q)
{
    if (IsEmpty(Q)) {
        perror("队列为空,无法执行出队操作\n");
        exit(EXIT_FAILURE);
    }
    else {
        Q->Size--;
        if (++Q->Front == Q->Capacity) {
            Q->Front = 0;
        }        
    }

}

// 判断队列是否为满
bool IsFull(PtrToQueue Q)
{
    return Q->Size == Q->Capacity;
}

// 判断队列是否为空
bool IsEmpty(PtrToQueue Q)
{
    return Q->Size == 0;
}

// 遍历队列
void TraverseQueue(PtrToQueue Q)
{
    if (Q->Size == 0) {
        printf("队列为空\n");
    }

    for (int i = 0; i < Q->Size; i++) {
        if (Q->Front + i < Q->Capacity) {
            printf("%d ", Q->Array[Q->Front + i]);
        }
        else {
            printf("%d ", Q->Array[Q->Front + i - Q->Capacity]);
        }    
    }

    printf("\n");
}

// 获取队头元素
ElementType Peek(PtrToQueue Q)
{
    return Q->Array[Q->Front];
}
View Code

   这段代码创建了一个队列,将整数 0~9分别入队,然后执行两次出队操作,再将整数 50 入队,程序执行结果如下:

 

参考资料:

《数据结构与算法分析 -- C语言描述》

posted @ 2019-04-29 22:37  tongye  阅读(4182)  评论(1编辑  收藏  举报