deque的简单介绍 & 优先级队列

目录

deque

空间结构:

迭代器:

deque的优缺点

优先级队列(priority_queue)

仿函数的概念

push()和top()

pop()

 size()和empty()

测试


deque

Dequdouble-e nded queue)双端队列,是一种可以在头尾两端进行插入和 删除操作且时间复杂度为O(1)的"连续"空间的数据结构

空间结构:

 deque是由一段段等长度的连续空间和一个map中控区(指针数组)所构成的,当空间不足时只需在开一个空间并将他链接到map,与list不同,deque不能保证将其所有元素存储在连续的存储位置.

迭代器:

dequr的迭代器维护起来相对复杂,是由四个指针一起来维护,node指向中控区,first和node分别指向一段空间的开始和结束,cur指向访问到的位置。如果访问的元素不在当前空间,cur就等于下一个空间的first,依次跑下去

deque的优缺点

与vector比较,deque的优势是:头部插入和删除时,不需要搬移元素,效率特别高,而且在扩容时,也不需要搬移大量的元素,因此其效率是必vector高的。

与list比较,其底层是连续空间,空间利用率比较高,不需要存储额外字段

deque有一个致命缺陷:不适合遍历,因为在遍历时,deque的迭代器要频繁的去检测其是否移动到 某段小空间的边界,导致效率低下。

 为什么选择deque作为stack和queue的底层默认容器

stack和queue不需要遍历(因此stack和queue没有迭代器),只需要在固定的一端或者两端进行操作。

优先级队列(priority_queue)

优先级队列(priority_queue)是一种容器适配器,优先级队列(priority_queue)其实并不像queue那样满足先进先出优先级队列中,将具有最高优先级的元素将被首先删除,

仿函数的概念

仿函数又称为函数对象,是一个能行使函数功能的类。

作为仿函数的类,都必须重载 operator() 运算符。因为调用仿函数,实际上就是通过类对象调用重载后的 operator() 运算符。
让我们看两个例子

template<class T>
struct less
{
  bool operator()(const T& x1,const T& x2)
  {
    return x1 < x2;
  }
}
template<class T>
struct greater
{
  bool operator()(const T& x1,const T& x2)
  {
    return x1 > x2;
  }
}

我们看到 greater 和 less 都只是将 operator()运算符进行重载,只不过返回的真假结果不同。

和queue不同 priority_queue 多了一个仿函数类型的模板参数。且是缺省值,不传参数时,默认使用less将优先级最高的元素弹出。

priority_queue的成员函数: 

 

模拟实现一个简单的priority_queue

模拟实现的priority_queue的成员函数:

1.push() :入队。向队列添加一个元素;
2.pop() :将队列中优先级最高的元素删除(出队)
3.top() :获得队列优先级最高的元素。
4.size() :获得队列大小。
5.empty() :判断队列是否为空

priority_queue的底层就像数据类型中的“堆”一样,将元素从堆顶弹出

不传第三个参数时,默认是用less,会将优先级最高的元素弹出。

当我们第三参数传greater时,会弹出优先级最低的元素。

push()和top()

push的时候每次都将有限级最高(或最低)的元素排在队头,top的时候将队头的数据弹出

template<class T,class Container=vector<T>,class compare=less<T>>
{
  public:

      //向上调整,将最大(或最小)的元素排到堆顶
      void AdjustUp(int child)
      {
        compate com; //仿函数类型
        int parent=(child-1)/2;child的根节点
        while(child > 0) 
        {
           //这里的_con()是被operator()重载过得,返回的是一个bool值
            if(com(_con[parent],_con[child]))
            {
              //向上调整,将最大(或最小)的元素排到堆顶
              swap(con[child],_con[parent]);
              child=parent;
              parent=(child-1)/2;
            }
            else
            {
              break;
            }
        }
      }

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

       T& top()
       {
          return _con[0] //将第一个元素弹出
       }
          
  private:
      container _con;
}

pop()

pop先将第一个元素和最后一个元素交换,将最后一个弹出,但是交换过后存储的数据就乱了,我们还需用向下调整法将数据的一个元素调整为优先级最高的(或最低的),

template<class T,class Container=vector<T>,class compare=less<T>>
{
  public:
   
  
      void AddjustDown()
      {
        Compare com; 定义一个仿函数类型
        int child=rood*2+1; 找到根的孩子
        while(child < _con.size())
        {
          //选出左右孩子中大(或下的)的那一个
          if(child+1<con.zize() && com(_con[child],_con[child+1])
          {
            ++child;
          }

          if(com[_con[child],_con[parent]); 
          {
            swap(_con[child],_con[parent]);
            parent=child;
            child=parent*2+1;
          }
          else
          {
            break;
          }

        } 
      }

      void push()
      {
        swap(_con[0],con[con.size()-1);//将我们需要pop的元素交换到尾
        _con.pop_back() //弹出队尾元素;
        AddjustDown(0)将数据的第一个元素调整为优先级最高的(或最低的)
      }
          
  private:
      container _con;
}

 size()和empty()

template<class T,class Container=vector<T>,class compare=less<T>>
{
  public:
      size_t size()
      {
        return _con.size();
      }

      bool empty()
      {
        return _con.empty();
      }
  private:
      container _con;
}

测试

   void test_priority_queue()
	{
       //默认大的优先级比较高
		priority_queue<int,vector<int>,less<int>> pq;		 
        pq.push(3);
		pq.push(1);
		pq.push(9);
		pq.push(4);
		pq.push(2);
		pq.pop();

        cout<<"pq: ";
		while (!pq.empty())
		{
			cout << pq.top() << " ";
			pq.pop();
		}
		cout << endl;
   
        //默认小的有限级高
		priority_queue<int, vector<int>, greater<int>> pq2;  
		pq2.push(3);
		pq2.push(1);
		pq2.push(9);
		pq2.push(4);
		pq2.push(2);
		pq2.pop();
         
        cout<<"pq2: ";
		while (!pq2.empty())
		{
			cout << pq2.top() << " ";
			pq2.pop();
		}
		cout << endl;

	}

测试结果 

本篇就分享到这里如果本文对您有帮助请点赞支持一下~

文章尚有不足,欢迎大牛指正

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值