Pin-Jiun / Programming-Language-CPP

It's the note/experience about C++, and I have the basic ability of C.
0 stars 0 forks source link

16-STL Container priority_queue (heap) #20

Open Pin-Jiun opened 1 year ago

Pin-Jiun commented 1 year ago

priority_queue

歸類在queue, 只需要 #include <queue> 就好

image

宣告

priority_queue預設使用vector轉換成priority_queue priority_queue <int> pq 預設為max heap(最大的優先取出)=priority_queue<int,vector<int>,less<int> >

若要改成最小的優先取出,需要在宣告時就告知是最小的優先取出,使用函式物件(function object)的greater<int> priority_queue<T, vector<T>, greater<T> > pq; 改成由小排到大

    int myints[]= {10,60,50,20};
    priority_queue<int> first;
    priority_queue<int> second (myints,myints+4);
    priority_queue<int, vector<int>, greater<int> >
                                third (myints,myints+4);

常見method(沒有 front() back())

empty() size() push() pop()

priority_queue.top() Returns a constant reference to the top element in the priority_queue.

priority_queue.pop() Removes the element on top of the priority_queue, effectively reducing its size by one.


// C++ program to create a priority queue of pairs.
// By default a max heap is created ordered
// by first element of pair.
#include <iostream>
#include <queue>

using namespace std;

// Driver program to test methods of graph class
int main()
{
    // By default a max heap is created ordered
    // by first element of pair.
    priority_queue<pair<int, int> > pq;

    pq.push(make_pair(10, 200));
    pq.push(make_pair(20, 100));
    pq.push(make_pair(15, 400));

    pair<int, int> top = pq.top();
    cout << top.first << " " << top.second;
    return 0;
}

範例1 會使用第一個數字當作key進行排列

#include <iostream>
#include <queue>
using namespace std;
#define pii pair<int,int>

int main(){
    priority_queue <pii, vector<pii> > pq;
    pq.push({4, 5});
    pq.push({5, 3});
    pq.push({4, 8});
    pq.push({2, 7});
    pq.push({3, 2});

    while (!pq.empty()){
        auto now = pq.top();
        pq.pop();
        cout << now.first << " " << now.second << endl;
    }
}

output1

Output:
5 3
4 8
4 5
3 2
2 7

範例2

#include <iostream>
#include <queue>
using namespace std;
#define pii pair<int,int>
#define F first
#define S second

int main(){
    priority_queue <pii, vector<pii>, greater<pii> > pq;
    pq.push({4, 5});
    pq.push({5, 3});
    pq.push({4, 8});
    pq.push({2, 7});
    pq.push({3, 2});

    while (!pq.empty()){
        auto now = pq.top();
        pq.pop();
        cout << now.F << " " << now.S << endl;
    }
}

output2

Output:
2 7
3 2
4 5
4 8
5 3

參考資料 https://yuihuang.com/cpp-stl-priority-queue/ https://ithelp.ithome.com.tw/articles/10269601 https://www.geeksforgeeks.org/priority-queue-of-pairs-in-c-ordered-by-first/

Pin-Jiun commented 1 year ago

priority_queue with tuple

首先先使用struct建立priority_queue

#include <queue>
using namespace std;
struct S
{
    int m_n1;
    int m_n2;
    int m_n3;

    S(int n1, int n2, int n3) : m_n1(n1), m_n2(n2), m_n3(n3)
    {
    }

    bool operator<(const struct S& other) const
    {
        //Your priority logic goes here
        return m_n1 < other.m_n1;
    }
};

int main()
{
    priority_queue<S> pq;

    //Add the elements to the queue
    pq.push(S(1,2,3));
    pq.push(S(4,2,3));
    pq.push(S(2,2,3));

    //This element will be S(4,2,3)
    S s1 = pq.top();
    pq.pop();

    return 0;
}
#include <tuple>
#include <iostream>
#include <queue>
using namespace std;

void print(priority_queue<tuple<int, 
           int, char> > priorityQueue)
{
  while (!priorityQueue.empty()) 
  {
    // Each element of the priority
    // queue is a tuple itself
    tuple<int, int, char> Tuple = 
          priorityQueue.top();

    cout << "[ ";

    cout << get<0>(Tuple) << ' ' << 
            get<1>(Tuple) << ' ' << 
            get<2>(Tuple);
    cout << ']';
    cout << '\n';

    // Pop out the topmost tuple
    priorityQueue.pop();
  }
}

int main()
{
    // Declaring a priority queue of tuple
    priority_queue<tuple<int, int, char> > priorityQueue;
    // Declaring a tuple
    tuple<int, int, char> tuple1;
    // Initializing the tuple
    tuple1 = make_tuple(5, 1, 'G');

    // Pushing the tuple in the priority queue
    priorityQueue.push(tuple1);

    // Declaring another tuple
    tuple<int, int, char> tuple2(2, 5, 'e');
    priorityQueue.push(tuple2);

    // Declaring another tuple
    tuple<int, int, char> tuple3(4, 3, 'k');
    priorityQueue.push(tuple3);

    print(priorityQueue);

    return 0;
}

output

[ 5 1 G]
[ 4 3 k]
[ 2 5 e]

working of customized priority queue of tuples

// C++ program to implement
// the above approach
#include <bits/stdc++.h>
using namespace std;

// Comparator
// we can use class also but then
// we will need to make the function
// public as class is by default private
struct myComparator
{
int operator()(const tuple<int, int,
                string>& tuple1,
                const tuple<int, int,
                string>& tuple2)
{
    // Second element of tuples is equal
    if (get<1>(tuple1) == get<1>(tuple2))
    {
    // first element of tuples is equal
    if (get<0>(tuple1) == get<0>(tuple2))
    {
        if (get<2>(tuple1) <= get<2>(tuple2))
        return true;
        return false;
    }

    return get<0>(tuple1) <= get<0>(tuple2);
    }

    return get<1>(tuple1) <= get<1>(tuple2);
}
};

// Function to print priority queue
// contents. Deliberately passing it
// call by value since we don't want
// to remove elements from the priority
// queue
void print(priority_queue<tuple<int, int,
        string>,
        vector<tuple<int, int, string> >,
        myComparator> priorityQueue)
{
while (!priorityQueue.empty())
{
    // Each element of the priority
    // queue is a tuple itself
    tuple<int, int, string> Tuple =
        priorityQueue.top();

    cout << "[ ";

    cout << get<0>(Tuple) << ' ' <<
            get<1>(Tuple) << ' ' <<
            get<2>(Tuple);
    cout << ']';
    cout << '\n';

    // Pop out the topmost tuple
    priorityQueue.pop();
}
}

// Driver code
int main()
{
// Declaring a priority queue of
// tuples by passing a custom comparator
priority_queue<tuple<int, int, string>,
vector<tuple<int, int, string> >,
myComparator>
    priorityQueue;

// Declaring a tuple
tuple<int, int, string> tuple1;

// Initializing the tuple
tuple1 = make_tuple(0, 0,
                    "Geeks");

// Pushing the tuple in the
// priority queue
priorityQueue.push(tuple1);

// Declaring a tuple
tuple<int, int, string> tuple2;

// Initializing the tuple
tuple2 = make_tuple(0, 1,
                    "Programming");

// Pushing the tuple in the
// priority queue
priorityQueue.push(tuple2);

// Declaring a tuple
tuple<int, int, string> tuple3;

// Initializing the tuple
tuple3 = make_tuple(1, 2,
                    "Geeks");

// Pushing the tuple in the
// priority queue
priorityQueue.push(tuple3);

// Declaring a tuple
tuple<int, int, string> tuple4;

// Initializing the tuple
tuple4 = make_tuple(1, 3,
                    "Programming");

// Pushing the tuple in the
// priority queue
priorityQueue.push(tuple4);

// Calling print function
print(priorityQueue);

return 0;
}
Pin-Jiun commented 1 year ago
// The debugger cannot handle symbols that are longer than 255 characters.
// STL frequently creates symbols that are longer than 255 characters.
// When symbols are longer than 255 characters, the warning is disabled.
#pragma warning(disable:4786)
#include "stdafx.h"
#include <queue>

#using <mscorlib.dll>

#if _MSC_VER > 1020 // if VC++ version is > 4.2
  using namespace std; // std c++ libs implemented in std
#endif
using namespace System;

//Define a custom data type.
class Student
{
    public:
    char* chName;
    int nAge;
    Student(): chName(""),nAge(0){}
    Student( char* chNewName, int nNewAge ):chName(chNewName), nAge(nNewAge){}
    };

    //Overload the < operator.
    bool operator< (const Student& structstudent1, const Student &structstudent2)
    {
        return structstudent1.nAge > structstudent2.nAge;
    }
    //Overload the > operator.
    bool operator> (const Student& structstudent1, const Student &structstudent2)
    {
        return structstudent1.nAge < structstudent2.nAge;
    }

    int _tmain()
    {
      //Declare a priority_queue and specify the ORDER as <
      //The priorities will be assigned in the Ascending Order of Age
      priority_queue<Student, vector<Student>,less<vector<Student>::value_type> > pqStudent1;

      //declare a priority_queue and specify the ORDER as >
      //The priorities will be assigned in the Descending Order of Age
      priority_queue<Student, vector<Student>,greater<vector<Student>::value_type> > pqStudent2;

      // Add container elements.
      pqStudent1.push( Student( "Mark", 38 ));
      pqStudent1.push( Student( "Marc", 25 ));
      pqStudent1.push( Student( "Bill", 47 ));
      pqStudent1.push( Student( "Andy", 13 ));
      pqStudent1.push( Student( "Newt", 44 ));

      //Display container elements.
      while ( !pqStudent1.empty())
      {
          cout << pqStudent1.top().chName << endl;
          pqStudent1.pop();
      }
      cout << endl;

      // Add container elements.
      pqStudent2.push( Student( "Mark", 38 ));
      pqStudent2.push( Student( "Marc", 25 ));
      pqStudent2.push( Student( "Bill", 47 ));
      pqStudent2.push( Student( "Andy", 13 ));
      pqStudent2.push( Student( "Newt", 44 ));

      //Display container elements.
      while ( !pqStudent2.empty())
      {
          cout << pqStudent2.top().chName << endl;
          pqStudent2.pop();
      }
      cout << endl;
      return 0;
    }
}

https://learn.microsoft.com/zh-tw/troubleshoot/developer/visualstudio/cpp/libraries/stl-priority-queue-class-custom-type