队列的定义

  • 队列是一种特殊的线性表
  • 队列仅能在线性表的两端进行操作

    • 队头(Front):取出数据元素的一端
    • 队尾(Rear):插入数据元素的一端

队列的特性

  • 先进先出 (First In First Out)

image.png

队列的操作

  • 创建队列 (Queue())
  • 销毁队列 (~Queue())
  • 清空队列 (clear())
  • 进队列 (add())
  • 出队列 (remove())
  • 获取队头元素 (front())
  • 获取队列的长度 (length())

队列的实现

template <typename T>
class Queue : public Object
{
public:
    virtual void add(const T &e) = 0;
    virtual void remove() = 0;
    virtual T front() const = 0;
    virtual void clear() = 0;
    virtual int length() const = 0;
};

image.png

队列的顺序实现

image.png

StaticQueue

  • 类模板

    • 使用原生数组作为队列的存储空间
    • 使用模板参数决定队列的最大容量
template <typename T, int N>
class StaticQueue : public Queue<T>
{
public:
    StaticQueue();  // 初始化成员变量
    int capacity() const;  
protected:
    T m_space[N];   // 队列存储空间,N为模板参数
    int m_front;    // 队头标识
    int m_rear;     // 队尾标识
    int m_length;   // 当前队列的长度
};

StaticQueue 实现要点 (循环计数法)

  • 关键操作

    • 进队列:m_space[m_rear] = e; m_rear = (m_rear + 1) % N;
    • 出队列:m_front = (m_front + 1) % N;
  • 队列的状态

    • 队空: (m_length == 0) && (m_front == m_rear)
    • 队满: (m_length == N) && (m_front == m_rear)

编程实验:基于顺序存储结构的队列

文件:Queue.h

#ifndef QUEUE_H
#define QUEUE_H

#include "Object.h"

namespace DTLib
{

template <typename T>
class Queue : public Object
{
public:
    virtual void add(const T &e) = 0;
    virtual void remove() = 0;
    virtual T front() const = 0;
    virtual void clear() = 0;
    virtual int length() const = 0;
};

}

#endif // QUEUE_H

文件:StaticQueue.h

#ifndef STATICQUEUE_H
#define STATICQUEUE_H

#include "Queue.h"
#include "Exception.h"

namespace DTLib
{

template <typename T, int N>
class StaticQueue : public Queue<T>
{
public:
    StaticQueue() = default;

    int capacity() const  // O(1)
    {
        return N;
    }

    void add(const T &e) override  // O(1)
    {
        if (m_length < N)
        {
            m_space[m_rear] = e;
            m_rear = (m_rear + 1) % N;
            ++m_length;
        }
        else
        {
            THROW_EXCEPTION(InvalidParameterExcetion, "No space in current StaticQueue ...");
        }
    }

    void remove() override  // O(1)
    {
        if (m_length > 0)
        {
            m_front = (m_front + 1) % N;
            --m_length;
        }
        else
        {
            THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current StaticQueue ...");
        }
    }

    T front() const override  // O(1)
    {
        if (m_length > 0)
        {
           return m_space[m_front];
        }
        else
        {
            THROW_EXCEPTION(InvalidOpertionExcetion, "No element in current StaticQueue ...");
        }
    }

    void clear() override  // O(1)
    {
        m_length = 0;
        m_front  = 0;
        m_rear   = 0;
    }

    int length() const override  // O(1)
    {
        return m_length;
    }

    ~StaticQueue()  // O(1)
    {
        clear();
    }

protected:
    T m_space[N];
    int m_front  = 0;
    int m_rear   = 0;
    int m_length = 0;
};

}

#endif // STATICQUEUE_H

文件: main.cpp

#include <iostream>
#include "StaticQueue.h"

using namespace std;
using namespace DTLib;


int main()
{
    StaticQueue<int, 5> queue;

    for (int i=0; i<5; ++i)
    {
        queue.add(i);
    }

    while (queue.length() > 0)
    {
        cout << queue.front() << endl;

        queue.remove();
    }

    return 0;
}

输出:

0
1
2
3
4

小结

  • 队列是一种特殊的线性表,具有先进先出的特性
  • 队列只允许在线性表的两端进行操作,一端进,一端出
  • StaticQueue 使用原生数组作为内部存储空间
  • StaticQueue 的最大容量由模板参数决定
  • StaticQueue 采用循环计数法提高队列操作的效率

以上内容整理于狄泰软件学院系列课程,请大家保护原创!


TianSong
737 声望139 粉丝

阿里山神木的种子在3000年前已经埋下,今天不过是看到当年注定的结果,为了未来的自己,今天就埋下一颗好种子吧