实现min函数

Implementing min function

本文关键字:函数 min 实现      更新时间:2023-10-16

您好,我发现了这个优先级队列实现,我正在尝试获得它的最小版本(而不是最大版本)。我不知道从哪里开始。我试着混合函数的符号(天真的尝试),但并没有让我走多远。任何关于如何实现它的帮助和几句解释它的话都是非常好的。来源如下:注意我已经留下了它的评论

#include <iostream>
#include <vector>
#include <assert.h>
using namespace std;
class PriorityQueue
{
    vector<int> pq_keys;
    void shiftRight(int low, int high);
    void shiftLeft(int low, int high);
    void buildHeap();
public:
    PriorityQueue(){}
    PriorityQueue(vector<int>& items)
    {
        pq_keys = items;
        buildHeap();
    }
    /*Insert a new item into the priority queue*/
    void enqueue(int item);
    /*Get the maximum element from the priority queue*/
    int dequeue();
    /*Just for testing*/
    void print();
};
void PriorityQueue::enqueue(int item)
{
    pq_keys.push_back(item);
    shiftLeft(0, pq_keys.size() - 1);
    return;
}
int PriorityQueue::dequeue()
{
    assert(pq_keys.size() != 0);
    int last = pq_keys.size() - 1;
    int tmp = pq_keys[0];
    pq_keys[0] = pq_keys[last];
    pq_keys[last] = tmp;
    pq_keys.pop_back();
    shiftRight(0, last-1);
    return tmp;
}
void PriorityQueue::print()
{
    int size = pq_keys.size();
    for (int i = 0; i < size; ++i)
        cout << pq_keys[i] << "   ";
    cout << endl;
}
void PriorityQueue::shiftLeft(int low, int high)
{
    int childIdx = high;
    while (childIdx > low)
    {
        int parentIdx = (childIdx-1)/2;
        /*if child is bigger than parent we need to swap*/
        if (pq_keys[childIdx] > pq_keys[parentIdx])
        {
            int tmp = pq_keys[childIdx];
            pq_keys[childIdx] = pq_keys[parentIdx];
            pq_keys[parentIdx] = tmp;
            /*Make parent index the child and shift towards left*/
            childIdx = parentIdx;
        }
        else
        {
            break;
        }
    }
    return;
}
void PriorityQueue::shiftRight(int low, int high)
{
    int root = low;
    while ((root*2)+1 <= high)
    {
        int leftChild = (root * 2) + 1;
        int rightChild = leftChild + 1;
        int swapIdx = root;
        /*Check if root is less than left child*/
        if (pq_keys[swapIdx] < pq_keys[leftChild])
        {
            swapIdx = leftChild;
        }
        /*If right child exists check if it is less than current root*/
        if ((rightChild <= high) && (pq_keys[swapIdx] < pq_keys[rightChild]))
        {
            swapIdx = rightChild;
        }
        /*Make the biggest element of root, left and right child the root*/
        if (swapIdx != root)
        {
            int tmp = pq_keys[root];
            pq_keys[root] = pq_keys[swapIdx];
            pq_keys[swapIdx] = tmp;
            /*Keep shifting right and ensure that swapIdx satisfies
            heap property aka left and right child of it is smaller than
            itself*/
            root = swapIdx;
        }
        else
        {
            break;
        }
    }
    return;
}
void PriorityQueue::buildHeap()
{
    /*Start with middle element. Middle element is chosen in
    such a way that the last element of array is either its
    left child or right child*/
    int size = pq_keys.size();
    int midIdx = (size -2)/2;
    while (midIdx >= 0)
    {
        shiftRight(midIdx, size-1);
        --midIdx;
    }
    return;
}
int main()
{
//example usage
    PriorityQueue asd;
    asd.enqueue(2);
    asd.enqueue(3);
    asd.enqueue(4);
    asd.enqueue(7);
    asd.enqueue(5);
    asd.print();
    cout<< asd.dequeue() << endl;
    asd.print();
    return 0;
}

通常在此类问题中,即基于元素比较的算法中,您可以重新定义(a < b)的含义。(顺便说一句,标准库中的东西就是这样工作的。你可以定义自己的比较器。)

所以如果你把它的意思改成相反的意思。您将颠倒顺序。

你需要识别每个元素的比较,并切换它

  /*if child is bigger than parent we need to swap*/
    if (pq_keys[childIdx] > pq_keys[parentIdx])

颠倒它的意义/逻辑。

简单的否定应该起作用:

  /*if child is NOT bigger than parent we need to swap*/
    if !(pq_keys[childIdx] > pq_keys[parentIdx])

你们甚至不需要理解算法。只是较小元素的相反含义。

编辑:附加说明。实际上,您可以将它重构为某种bool compare(T a, T b)。在使用比较的情况下使用此函数。因此,每当你想改变行为时,你只需要改变一个地方,它就会始终如一。但这主要是为了避免寻找每一个这样的事件,以及愚蠢的错误和你错过的错误。

更简单:

std::prioroty_queue<int, std::vector<int>, std::greater<int>> my_queue;

如果这是练习的一部分,那么我建议遵循标准库的设计原则:将问题分解:

  1. 数据存储(例如std::vector)
  2. 排序或"堆积"算法(参见std::make_heap等)
  3. 订购标准(由2。以上)

你的课应该给你一些余地,让你独立地改变其中的任何一个。有了这一点,您可以简单地将"小于"的排序更改为"大于"的排序。