【慢速学数据结构】队列篇

概述

队列ADT我相信大家都很清楚,就是FIFO嘛。

这一篇,关键讲队列怎么实现。

实现

循环数组实现。

template<typename T>
class Queue_array
{
public:
    Queue_array(int maxsize = 10) : maxsize_(maxsize), 
                                    size_(0), front_(1), rear_(0)
    {
        pa_ = new T[maxsize_];// 初始化数组,默认大小为10
    }
    virtual ~Queue_array()
    {
        delete[] pa_;
    }

public:
    void push(const T& x)
    {
        if (isFull())
            return;

        size_++;
        rear_++;
        rear_ %= maxsize_;// 让rear在将要越界的时候,回到0,从而实现循环

        *(pa_ + rear_) = x;
    }
    void pop()
    {
        size_--;
        front_++;
        front_ %= 10;// 不要忘了,这里也要加
    }
    const T getFront()
    {
        return *(pa_ + front_);
    }
    const int getSize() const
    {
        return size_;
    }
    bool isEmpty() const
    {
        return size == 0;
    }
    bool isFull() const
    {
        return size_ == maxsize_;
    }

private:
    int front_, rear_;
    T* pa_;
    int size_;
    int maxsize_;
};

链表实现

template<typename T>
class Queue_list {
public:
    typedef struct list {
        T data;
        list *next;
        list(T x) : data(x), next(nullptr) {}
    } ListNode;

    Queue_list(int maxsize = 10) : size_(0), maxsize_(maxsize) {
        front_ = rear_ = new ListNode(0);// 初始化,front和rear都指向同一个结点
    }

    virtual ~Queue_list() {
        while( front_ != rear_) {
            ListNode* t = front_->next;
            delete front_;
            front_ = t;
        }
        delete rear_;
    };
public:
    // 插到rear现在所在的位置,并且新增一个结点让rear指向它
    void push( const T& x) {
        size_++;
        rear_->data = x;
        rear_->next = new ListNode(0);
        rear_ = rear_->next;
    }

    // 删除front现在指向的结点,将front指向下一个结点
    void pop() {
        size_--;
        ListNode *t = front_;
        front_ = front_->next;
        delete t;
    }

    const T getFront() {
        return front_->data;
    }

    const int getSize() const {
        return size_;
    }

    bool isEmpty() const {
        return front == rear;
    }

    // 链表实现可以不考虑队列满的情况
private:
    ListNode *front_, *rear_;
    int size_;
    int maxsize_;
};

测试用例:

int main() {
    {
        Queue_list<int> q;
        for(auto i = 0; i<10; i++)
            q.push(i);
        q.pop();
        assert(9 == q.getSize());
        assert(1 == q.getFront());
        q.push(10);
        q.pop();
        assert(2 == q.getFront());
    }

    {
        Queue_array<int> q;
        for(auto i = 0; i<10; i++)
            q.push(i);
        q.pop();
        assert(9 == q.getSize());
        assert(1 == q.getFront());
        q.push(10);
        q.pop();
        assert(2 == q.getFront());
    }


    std::cout << "All test cases pass";
    return 0;
}

应用

来学习一下STL里的deque,cppreference里对它的大概描述是:

deque(double end queue 双端队列),随机访问时间O(1),插入头和尾结点的时间是O(1),普通插入的时间是O(N)。它的存储是由多个固定大小的数组组成,而且在动态扩充大小的时候效率很高,不会像vector那样,将所有的内容重新复制到新的内存中。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值