从零开始的C++(十三)

优先级队列(priority_queue),是一种基于堆实现的有序数组,效果是插入元素后会自动排序,使得遍历时会一直呈现一种有序。默认情况下会按照降序排列,可以自定义排列方式

模拟实现:

优先级队列实现主要包括两部分,一个是优先级队列本身的实现,一个是自定义排列的类模版。

1、优先级队列:

 template , class Compare = less >
    class priority_queue

    {

    public:

        priority_queue()
        {

        }

        template 

        priority_queue(InputIterator first, InputIterator last)
            :c( first, last)
        {

        }

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

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

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

        void push(const T& x)
        {   
            //尾插
            c.push_back(x);
            //向上替换
            adjustup();
        }

        void adjustup()
        {
            int child = c.size()-1;
            int parent = (child - 1) / 2;
            while (child > 0)
            {
                //左小于右
                if (comp(c[parent], c[child]))
                {
                    swap(c[child], c[parent]);
                    child = parent;
                    parent = (child - 1) / 2;
                }
                else
                {
                    break;
                }
            }
        }


        void pop()
        {  
            //交换
            swap(c[0], c[c.size()-1]);
            c.pop_back();

            adjustdown(0);
        }

      void adjustdown(int x)
      {
          int parent = x;
          int child = x * 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[child], c[parent]);
                  parent = child;
                  child = child * 2 + 1;
              }
              else
              {
                  break;
              }


          }


      }

    private:

        Container c;

        //默认大堆
        Compare comp;

    };

1.由于成员是类模版或者容器定义的对象,因此默认构造函数内可以不写,编译器会自动调用成员对象的默认构造函数。传迭代器的构造函数同理,利用初始化列表可以调用成员对象自己对应的构造函数。但是,由于自定义了传迭代器的构造函数,编译器不会自己写默认构造函数,因此需要自己手动写一个默认构造函数。

2.对于empty()、size()、top()可以复用成员自己对应的函数。

3.对于push和pop函数,需要手动写一些函数,如实现堆的向下排序和向上排序法。

对于push函数,实现思路是首先在尾部插入一个元素,然后不断和其父元素比较,判断大小决定是否和父元素互换。

对于pop函数,实现思路是首先交换首位元素,然后去掉尾元素,后交换到首部的元素不断和其子元素比较,确定是否互换。

在判断大小那里,使用了伪函数(效果类似函数指针),从而实现了自定义比较方式。

2、定义排列的类模版

  template
    struct Less
    {

        bool operator()(T& x, T& y)
        {
            return x > y;
        }

    };

该类内实现了伪函数,即operator()(参数列表),实现了当x大于y的时候才互换,从而影响了上面pop函数和push函数内的交换逻辑。

利用优先级队列,可以很方便解决类似求一堆数中的第k大(小)的数或前k大(小)的数。 

你可能感兴趣的:(c++,开发语言)