zoukankan      html  css  js  c++  java
  • 基本数据结构 -- 队列(数组实现)

      队列是一种先进先出(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!
    ");
            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("队列已满,入队失败
    ");
            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("队列为空,无法执行出队操作
    ");
            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("队列为空
    ");
        }
    
        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!
    ");
            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("队列已满,入队失败
    ");
            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("队列为空,无法执行出队操作
    ");
            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("队列为空
    ");
        }
    
        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("
    ");
    }
    
    // 获取队头元素
    ElementType Peek(PtrToQueue Q)
    {
        return Q->Array[Q->Front];
    }
    View Code

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

    参考资料:

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

  • 相关阅读:
    ajax入门之建立XHR对象 (1)
    JavaScript中的函数有什么特点? 应该怎样优化?
    什么是JavaScript中的面向对象? 与其他编程语言的面向对象有什么区别? 什么是原型?
    Web页面加载,如何分析页面性能?如何进行优化?
    一个页面从输入 URL 到页面加载完的过程中都发生了什么事情?
    关于清除浮动与闭合浮动
    如何更加安全快速的使用富文本编辑器
    用Python实现一个爬取XX大学电费通知的小脚本
    在Sublime Text3上面更加方便愉快的写php
    如何搭建一个WAMP环境
  • 原文地址:https://www.cnblogs.com/tongye/p/10779643.html
Copyright © 2011-2022 走看看