• 【数据结构】之队列(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("队列初始化失败!
    ");
            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("队列不存在,销毁失败!
    ");
            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("队列不存在!
    ");
            exit(1);
        }
        if(Q->length == 0) {
            return TRUE;
        }
        return FALSE;
    }
    
    // 清空队列
    Status clearQueue(Queue* Q) {
        QueueNode* node;
        if(Q->data == NULL) {
            printf("队列不存在,清空失败!
    ");
            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("队列不存在!
    ");
            exit(1);
        }
        return Q->length;
    }
    
    // 查看队列中的第一个元素
    QueueNode* getFirstElem(Queue* Q) {
        if(Q->data == NULL) {
            printf("队列不存在,获取第一个元素失败!
    ");
            return NULL;
        }
        if(Q->length == 0) {
            printf("队列是空队列,获取第一个元素失败!
    ");
            return NULL;
        }
        return Q->firstNode;
    }
    
    // 查看队列中的最后一个元素
    QueueNode* getLastElem(Queue* Q) {
        if(Q->data == NULL) {
            printf("队列不存在,获取最后一个元素失败!
    ");
            return NULL;
        }
        if(Q->length == 0) {
            printf("队列是空队列,获取最后一个元素失败!
    ");
            return NULL;
        }
        return Q->lastNode;
    }
    
    // 元素入队列
    Status appendElem(Queue* Q, ElemType e) {
        QueueNode* newNode;
        if(Q->data == NULL) {
            printf("队列不存在,元素入队列失败!
    ");
            return FAILURE;
        }
        newNode = (QueueNode*)malloc(sizeof(QueueNode));
        if(newNode == NULL) {
            printf("元素入队列失败!
    ");
            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("队列不存在,元素出队列失败!
    ");
            return NULL;
        }
        if(Q->length == 0) {
            printf("队列是空队列,元素出队列失败!
    ");
            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("队列不存在,遍历失败!
    ");
            exit(1);
        }
        if(Q->length == 0) {
            printf("队列是空队列,遍历失败!
    ");
            exit(1);
        }
        printf("遍历队列:");
        node = Q->data;
        while((node = node->nextNode) != NULL) {
            printf("%-4d", node->value);
        }
        printf("
    ");
    }
    
    // 测试队列的方法
    int testQueue() {
        // 各种对象的声明
        Queue queue;
        QueueNode* node;
        int i = 0;
        // 初始化队列
        if(initQueue(&queue) == SUCCESS) {
            printf("队列初始化成功!
    ");
        }
        // 入队列
        for(i = 1; i <= 5; i++) {
            if(appendElem(&queue, i) == SUCCESS) {
                printf("元素%d入队列成功!
    ", i);
            }
        }
        // 出队列
        if((node = retrieveElem(&queue)) != NULL) {
            printf("元素%d被移除队列
    ", node->value);
        }
        // 查看队列中的第一个元素
        if((node = getFirstElem(&queue)) != NULL) {
            printf("队列中第一个元素的值是:%d
    ", node->value);
        }
        // 查看队列中的最后一个元素
        if((node = getLastElem(&queue)) != NULL) {
            printf("队列中最后一个元素的值是:%d
    ", node->value);
        }
        // 获取队列中元素的个数
        printf("队列中元素的个数:%d
    ", getQueueSize(&queue));
        // 遍历队列中的元素
        traverseQueue(&queue);
        // 判断队列是否为空
        printf("队列是否为空?%s
    ", isQueueEmpty(&queue) == TRUE ? "" : "");
        // 清空队列
        if(clearQueue(&queue) == SUCCESS) {
            printf("清空队列成功!
    ");
        }
        // 销毁队列
        if(destroyQueue(&queue) == SUCCESS) {
            printf("队列销毁成功!
    ");
        }
    }

      常量类 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.
  • 相关阅读:
    数据库锁表处理汇总
    2021,顺其自然
    NetCore中跨域策略的一个坑
    Furion框架亮点之-动态WebAPI
    sql中where in的数量限制
    动态规划学习笔记
    用Go编写Web应用程序
    Asp.net Core AutoFac根据程序集实现依赖注入
    Linux+Docker+Gitee+Jenkins自动化部署.NET Core服务
    CentOS8.0安装Nacos
  • 原文地址:https://www.cnblogs.com/itgungnir/p/6672266.html
Copyright © 2020-2023  润新知