栈与队列及优先级队列

1.Stack介绍

  stack是一种容器适配器,特点是后进先出,只能从容器的一端进行提取、插入、删除。stack的底层容器一般使用deque,除此之外list,vector也符合容器特性。

(1)deque

  双端队列(Deque,全称为Double-Ended Queue)是一种具有队列和栈的性质的数据结构。它允许在队列的两端进行插入和删除操作,同时也具有先进先出(FIFO)和后进先出(LIFO)的特性。因此,双端队列是队列和栈的一种综合体。deque不仅能作为stack的底层容器,同时也能作为queue的底层容器。deque是一个非常实用的数据结构,它可以用来解决许多需要在队列头部和尾部进行频繁操作的问题。

(2)stack函数接口

  由于stack底层有一个容器,因此stack的成员也就只包含一个容器,通过调用容器的函数来满足stack的函数需求。

stack需要以下函数接口:

#pragma once
using namespace std;
#include <deque>

namespace L
{
	template <class T,class con = deque<T>>
	class stack
	{
    public:

        stack()
        {
            ;
        }

        void push(const T& x)
        {
            _con.push_back(x);
        }

        void pop()
        {
            _con.pop_back();
        }

        T& top()
        {
            return _con.back();
        }

        const T& top()const
        {
            return _con.back();
        }

        size_t size()const
        {
            return _con.size();
        }

        bool empty()const
        {
            return _con.empty();
        }

    private:
        con _con;
	};
}

 2.Queue介绍

  队列是一种容器适配器,特点是先进先出,从容器的一端插入元素,从另一端提取元素。其底层容器一般使用的是deque,如有特别要求,list也是能满足需求。

(1)queue函数接口

#pragma once
using namespace std;
#include <deque>

namespace L
{
    template <class T, class con = deque<T>>
    class queue
    {
    public:

        queue()
        {
            ;
        }

        void push(const T& x)
        {
            _c.push_back(x);
        }

        void pop()
        {
            _c.pop_front();
        }

        T& back()
        {
            return _c.back();
        }

        const T& back()const
        {
            return _c.back();
        }

        T& front()
        {
            return _c.front();
        }

        const T& front()const
        {
            return _c.front();
        }

        size_t size()const
        {
            return _c.size();
        }

        bool empty()const
        {
            return _c.empty();
        }

    private:

        con _c;
    };
}

 3.优先级队列

  优先级队列是一种容器适配器,特点是类似于堆,根据less排序,它的第一个元素总是最大元素,随时能进行插入元素,并且支持随机访问迭代器,而且内部需要始终保持堆结构。优先级队列的底层容器一般默认是vector,默认情况下优先级队列是大堆。

(1)函数接口

优先级队列也具有栈与队列相同的函数接口需求,只不过模拟实现的方式有点不同。

优先级队列的成员不仅具有容器,还具有仿函数成员。通过仿函数来确定是建大堆还是小堆。

构造函数:优先级队列提供默认的构造函数,还有通过迭代器区间来构造的函数。在通过迭代器区间来构造完成后,就需要进行建堆操作,而建堆则需要实现向下调整算法。

 priority_queue()
        {
            ;
        }

        template <class InputIterator>

        priority_queue(InputIterator first, InputIterator last)
        {
            while (first != last)
            {
                c.push_back(*first);
                ++first;
            }

            for (int i = (c.size() - 1 - 1) / 2; i >= 0; --i)
            {
                AdjustDown(i);
            }
        }
 

 

 void AdjustDown(size_t parent)
        {
            size_t child = parent * 2 + 1;
            
            while (child < c.size())
            {
                if (child + 1 < c.size() && comp(c[child], c[child + 1]))
                {
                    ++child;
                }
                if (comp(c[parent], c[child]))
                {
                    swap(c[parent], c[child]);
                    parent = child;
                    child = parent * 2 + 1;
                }
                else
                {
                    break;
                }
            }
        }

代码中comp是仿函数,默认是less算法,向下调整算法即谁小谁交换。

POP:在删除函数中,同样需要向下调整算法。思路和堆的删除思路一样,队首元素与队尾元素交换,然后直接调用尾删函数,接着使用向下调整算法来保持内部是堆的结构。

 void pop()
        {
            assert(c.size() > 0);
            swap(c[0], c[c.size() - 1]);
            c.pop_back();
            AdjustDown(0);
        }

 

PUSH:在插入函数中,由于是在队尾插入元素,因此需要向上调整算法。

void AdjustUp(size_t child)
        {
            size_t parent = (child - 1) / 2;
            while (child > 0)
            {
                if (comp(c[parent],c[child]))
                {
                    swap(c[parent], c[child]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }
 void push(const T& x)
        {
            c.push_back(x);
            AdjustUp(c.size() - 1);
        }

(2)完整模拟实现代码 

#pragma once
#include <vector>
#include <functional>
#include <assert.h>
using namespace std;

namespace L
{
    template <class T, class Container = vector<T>, class Compare = less<T> >

    class priority_queue

    {

    public:

        priority_queue()
        {
            ;
        }

        template <class InputIterator>

        priority_queue(InputIterator first, InputIterator last)
        {
            while (first != last)
            {
                c.push_back(*first);
                ++first;
            }

            for (int i = (c.size() - 1 - 1) / 2; i >= 0; --i)
            {
                AdjustDown(i);
            }
        }

        void AdjustUp(size_t child)
        {
            size_t parent = (child - 1) / 2;
            while (child > 0)
            {
                if (comp(c[parent],c[child]))
                {
                    swap(c[parent], c[child]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }

        void AdjustDown(size_t parent)
        {
            size_t child = parent * 2 + 1;
            
            while (child < c.size())
            {
                if (child + 1 < c.size() && comp(c[child], c[child + 1]))
                {
                    ++child;
                }
                if (comp(c[parent], c[child]))
                {
                    swap(c[parent], c[child]);
                    parent = child;
                    child = parent * 2 + 1;
                }
                else
                {
                    break;
                }
            }
        }

        bool empty() const
        {
            return c.empty();
        }

        size_t size() const
        {
            return c.size();
        }

        const T& top() const
        {
            return c[0];
        }

        void push(const T& x)
        {
            c.push_back(x);
            AdjustUp(c.size() - 1);
        }

        void pop()
        {
            assert(c.size() > 0);
            swap(c[0], c[c.size() - 1]);
            c.pop_back();
            AdjustDown(0);
        }

    private:

        Container c;

        Compare comp;

    };
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值