【数据结构】之队列(C语言描述)

  队列(Queue)是编程中最常用的数据结构之一。

  队列的特点是“先进先出”,就像食堂排队买饭一样,先来的人排在前面,后来的人排在后面;前面的人先买饭,买完饭后离开这个队列。这就是队列的原理,它可以进行入队列和出队列的操作,也就是说,队列限制用户只能在队列的前后两端进行操作,不能在中间进行操作。

  和线性表、栈相同,队列也有顺序的存储方式和链式的存储方式两种方式,分别称为顺序对和链队。与栈不同的是,队列可以在前后两个端点处进行增/删操作,因此,顺序队性能大大不如链队,链队是二者中比较常用的队列表示形式。

  下面的代码是使用 C语言 描述的链队的代码。

  队列的头文件Queue.h中的代码如下:

/**
 * 队列(链式存储)
 * 本程序中队列的存储方式:头节点->节点1->节点2->...->节点N,头结点中不存储数据
 */
#include <Constant.h>

// 定义队列节点中数据的类型
typedef int ElemType;

// 队列中节点的数据结构体
typedef struct QueueNode {
    ElemType value;
    struct QueueNode* nextNode;
} QueueNode;

// 队列的结构体
typedef struct Queue {
    QueueNode* data;
    QueueNode* firstNode;
    QueueNode* lastNode;
    int length;
} Queue;

// 初始化队列
Status initQueue(Queue* Q) {
    Q->data = (QueueNode*)malloc(sizeof(QueueNode));
    if(Q->data == NULL) {
        printf("队列初始化失败!\n");
        return FAILURE;
    }
    Q->data->nextNode = NULL;
    Q->firstNode = NULL;
    Q->lastNode = NULL;
    Q->length = 0;
    return SUCCESS;
}

// 销毁队列
Status destroyQueue(Queue* Q) {
    QueueNode* node;
    if(Q->data == NULL) {
        printf("队列不存在,销毁失败!\n");
        return FAILURE;
    }
    while(Q->data->nextNode != NULL) {
        node = Q->data->nextNode;
        Q->data->nextNode = node->nextNode;
        free(node);
    }
    free(Q->data);
    return SUCCESS;
}

// 判断队列是否为空
Status isQueueEmpty(Queue* Q) {
    if(Q->data == NULL) {
        printf("队列不存在!\n");
        exit(1);
    }
    if(Q->length == 0) {
        return TRUE;
    }
    return FALSE;
}

// 清空队列
Status clearQueue(Queue* Q) {
    QueueNode* node;
    if(Q->data == NULL) {
        printf("队列不存在,清空失败!\n");
        return FAILURE;
    }
    while(Q->data->nextNode != NULL) {
        node = Q->data->nextNode;
        Q->data->nextNode = node->nextNode;
        free(node);
    }
    return SUCCESS;
}

// 获取队列中元素的个数
int getQueueSize(Queue* Q) {
    if(Q->data == NULL) {
        printf("队列不存在!\n");
        exit(1);
    }
    return Q->length;
}

// 查看队列中的第一个元素
QueueNode* getFirstElem(Queue* Q) {
    if(Q->data == NULL) {
        printf("队列不存在,获取第一个元素失败!\n");
        return NULL;
    }
    if(Q->length == 0) {
        printf("队列是空队列,获取第一个元素失败!\n");
        return NULL;
    }
    return Q->firstNode;
}

// 查看队列中的最后一个元素
QueueNode* getLastElem(Queue* Q) {
    if(Q->data == NULL) {
        printf("队列不存在,获取最后一个元素失败!\n");
        return NULL;
    }
    if(Q->length == 0) {
        printf("队列是空队列,获取最后一个元素失败!\n");
        return NULL;
    }
    return Q->lastNode;
}

// 元素入队列
Status appendElem(Queue* Q, ElemType e) {
    QueueNode* newNode;
    if(Q->data == NULL) {
        printf("队列不存在,元素入队列失败!\n");
        return FAILURE;
    }
    newNode = (QueueNode*)malloc(sizeof(QueueNode));
    if(newNode == NULL) {
        printf("元素入队列失败!\n");
        return FAILURE;
    }
    newNode->value = e;
    newNode->nextNode = NULL;
    if(Q->data->nextNode == NULL) {
        Q->data->nextNode = newNode;
        Q->firstNode = newNode;
    } else {
        Q->lastNode->nextNode = newNode;
    }
    Q->lastNode = newNode;
    Q->length++;
    return SUCCESS;
}

// 元素出队列
QueueNode* retrieveElem(Queue* Q) {
    QueueNode* node;
    if(Q->data == NULL) {
        printf("队列不存在,元素出队列失败!\n");
        return NULL;
    }
    if(Q->length == 0) {
        printf("队列是空队列,元素出队列失败!\n");
        return NULL;
    }
    node = Q->data->nextNode;
    Q->data->nextNode = node->nextNode;
    Q->length--;
    return node;
}

// 遍历队列中的元素
void traverseQueue(Queue* Q) {
    QueueNode* node;
    if(Q->data == NULL) {
        printf("队列不存在,遍历失败!\n");
        exit(1);
    }
    if(Q->length == 0) {
        printf("队列是空队列,遍历失败!\n");
        exit(1);
    }
    printf("遍历队列:");
    node = Q->data;
    while((node = node->nextNode) != NULL) {
        printf("%-4d", node->value);
    }
    printf("\n");
}

// 测试队列的方法
int testQueue() {
    // 各种对象的声明
    Queue queue;
    QueueNode* node;
    int i = 0;
    // 初始化队列
    if(initQueue(&queue) == SUCCESS) {
        printf("队列初始化成功!\n");
    }
    // 入队列
    for(i = 1; i <= 5; i++) {
        if(appendElem(&queue, i) == SUCCESS) {
            printf("元素%d入队列成功!\n", i);
        }
    }
    // 出队列
    if((node = retrieveElem(&queue)) != NULL) {
        printf("元素%d被移除队列\n", node->value);
    }
    // 查看队列中的第一个元素
    if((node = getFirstElem(&queue)) != NULL) {
        printf("队列中第一个元素的值是:%d\n", node->value);
    }
    // 查看队列中的最后一个元素
    if((node = getLastElem(&queue)) != NULL) {
        printf("队列中最后一个元素的值是:%d\n", node->value);
    }
    // 获取队列中元素的个数
    printf("队列中元素的个数:%d\n", getQueueSize(&queue));
    // 遍历队列中的元素
    traverseQueue(&queue);
    // 判断队列是否为空
    printf("队列是否为空?%s\n", isQueueEmpty(&queue) == TRUE ? "" : "");
    // 清空队列
    if(clearQueue(&queue) == SUCCESS) {
        printf("清空队列成功!\n");
    }
    // 销毁队列
    if(destroyQueue(&queue) == SUCCESS) {
        printf("队列销毁成功!\n");
    }
}

  常量类 Constant.h 中定义了一些常量,其代码如下:

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

#define TRUE 1
#define FALSE 0

#define SUCCESS 1
#define FAILURE 0

typedef int Status;

  主函数所在的文件 main.c 中的代码如下:

#include <Queue.h>

int main() {
    testQueue();
    return 0;
}

  运行结果如下:

队列初始化成功!
元素1入队列成功!
元素2入队列成功!
元素3入队列成功!
元素4入队列成功!
元素5入队列成功!
元素1被移除队列
队列中第一个元素的值是:1
队列中最后一个元素的值是:5
队列中元素的个数:4
遍历队列:2   3   4   5
队列是否为空?否
清空队列成功!
队列销毁成功!

Process returned 0 (0x0)   execution time : 1.743 s
Press any key to continue.

 

posted on 2017-04-06 10:24  ITGungnir  阅读(931)  评论(0编辑  收藏  举报

导航