STL priority_queue(优先队列)详解

STL priority_queue(优先队列)详解

什么是 STL priority_queue?

STL priority_queue 是一种基于堆的数据结构,用于实现优先队列,即能够按照特定的优先级顺序(默认为大顶堆)存储和访问元素。它是一个模板类,可以存储任何类型的数据,保证了插入元素和删除元素的时间复杂度都为 $O(logN)$。

如何使用 STL priority_queue?

我们可以通过以下代码定义一个 STL priority_queue:

priority_queue<int> pq;

这行代码定义了一个存储 int 类型数据的空优先队列。我们可以用以下代码向其中插入元素:

pq.push(3);
pq.push(1);
pq.push(4);
pq.push(1);

以上代码中,push 操作用于向优先队列中插入元素。因为默认情况下优先队列采用的是大顶堆,所以以上代码会在优先队列中创建一个如下的堆:

         4
        / \
       3   1
      /
     1

接下来,我们可以用以下代码访问队首元素并删除它:

int top = pq.top();
pq.pop();

这段代码将访问队首元素 4,将其从队列中删除,并将其赋值给 top 变量。执行完成后,优先队列中剩余的元素为:

         3
        / 
       1    
      /
     1

我们称这个操作为弹出栈顶元素。

优先级定制

默认情况下,优先队列采用的是大顶堆排序,即根据元素的大小来进行排序。但是,我们也可以自定义优先级排序方式,以实现我们特定的需求。

假设我们需要存储一个有编号和重要性的任务列表,并按照重要性进行排序。我们可以通过以下代码定义一个包含任务信息的结构体:

struct Task {
    int id;
    int importance;
    bool operator<(const Task& t) const {
        return importance < t.importance;
    }    
};

该结构体中包含任务编号和重要性属性,并通过重载小于号运算符实现了自定义的比较方式。

接下来,我们可以通过以下代码定义一个存储 Task 类型数据的优先队列,并向其中插入几个任务:

priority_queue<Task> taskList;
taskList.push({1, 5});
taskList.push({2, 3});
taskList.push({3, 9});
taskList.push({4, 7});

假设以上任务列表中任务编号为 3 的任务的重要性最高,我们可以使用以下代码访问并弹出队首元素,即取出编号为 3 的任务:

Task topTask = taskList.top();
taskList.pop();

执行完以上代码后,topTask 结构体中的值为 {3, 9},任务列表中剩余元素为:

{4, 7}
{1, 5}
{2, 3}

由此可见 STL priority_queue 具有非常高的可扩展性,开发者可以根据实际需求灵活运用此数据结构。

示例说明

示例一:求数据流中的中位数

假设有一组数据流,需要求这个数据流中的中位数,即中间位置的数。我们可以通过以下代码使用两个 STL priority_queue 来实现:

priority_queue<int> maxHeap; // 大顶堆,用于存储较小的一半数据
priority_queue<int, vector<int>, greater<int>> minHeap; // 小顶堆,用于存储较大的一半数据
int median = 0;

void insert(int num) {
    if (maxHeap.empty() || num <= maxHeap.top()) {
        maxHeap.push(num);
    } else {
        minHeap.push(num);
    }
    // 平衡两个堆的大小
    if (maxHeap.size() - minHeap.size() > 1) {
        minHeap.push(maxHeap.top());
        maxHeap.pop();
    } else if (minHeap.size() - maxHeap.size() > 1) {
        maxHeap.push(minHeap.top());
        minHeap.pop();
    }
    // 计算中位数
    if (maxHeap.size() > minHeap.size()) {
        median = maxHeap.top();
    } else if (maxHeap.size() < minHeap.size()) {
        median = minHeap.top();
    } else {
        median = (maxHeap.top() + minHeap.top()) / 2;
    }
}

int getMedian() {
    return median;
}

以上代码中,我们定义了一个大顶堆 maxHeap 和一个小顶堆 minHeap,用来存储数据流中的数。我们将数据流中的较小数放入大顶堆中,较大数放入小顶堆中,并为了保持两个堆的平衡性而实时调整两个堆的大小和取数方式。最后,我们可以通过 getMedian() 方法获得数据流的中位数。

示例二:最后 K 个数中的最大数

假设有一个数流,且数量较大,我们需要从数流中取出最后 K 个数中的最大值。我们可以通过以下代码使用 STL priority_queue 来实现:

priority_queue<int> maxHeap;

void insert(int num) {
    maxHeap.push(num);
    if (maxHeap.size() > K) {
        maxHeap.pop();
    }
}

int getMax() {
    return maxHeap.top();
}

以上代码中,我们定义了一个大顶堆 maxHeap,每次将数流中的数插入到大顶堆中,并维护堆的大小以保证堆中只有最后 K 个插入的数。最后,我们可以通过 getMax() 方法返回最终的最大值。

本站文章如无特殊说明,均为本站原创,如若转载,请注明出处:STL priority_queue(优先队列)详解 - Python技术站

(0)
上一篇 2023年6月27日
下一篇 2023年6月27日

相关文章

  • golang使用ssh远程连接服务器并执行命令

    golang使用ssh远程连接服务器并执行命令 在开发过程中,我们经常需要使用ssh协议连接到远程服务器并执行命令。golang中提供了一个ssh包,可以方便地实现ssh连接服务器。本文将解释如何使用golang实现ssh连接服务器并执行命令。 1. 安装ssh包 ssh包是官方标准库中的一部分,您可以直接使用它,而无需安装其他软件包。要使用ssh包,请在代…

    其他 2023年3月28日
    00
  • bat切换目录运行

    以下是在Windows中使用bat切换目录运行的完整攻略: 在Windows中使用bat切换目录运行 在Windows中,您可以使用bat文件来切换目录并运行命令。以下是实现效果的步骤: 打开文本编辑器,创建一个新的bat文件。 在bat文件中使用cd命令切换到目标目录。 cd C:\Users\username\Documents\ 在上面的代码中,我们使…

    other 2023年5月7日
    00
  • 利用SQL语句给字段加注释的方法

    给字段加注释是一种很好的数据库维护方法,可以帮助开发人员更好地理解数据库中的字段含义,从而提高数据库开发和维护效率。以下是利用SQL语句给字段加注释的完整攻略: 步骤1:查看表结构 在给字段加注释之前,首先需要查看表结构,确定需要加注释的字段名称和数据类型。可以使用SQL的DESCRIBE语句来查看一个表的结构。 下面是查看“users”表结构的示例代码: …

    other 2023年6月25日
    00
  • Nginx+php配置文件及原理解析

    Nginx是一个轻量级的web服务器软件,而PHP是一种流行的Web编程语言,使用Nginx服务器来处理PHP应用程序可以提高Web应用程序的性能和并发性能。本文将详细介绍如何通过Nginx服务器和php配置文件来配置和运行PHP应用程序。具体内容如下: 准备工作 在开始之前,请确保已经安装了Nginx和PHP。如果没有,请执行以下步骤进行安装: # 安装N…

    other 2023年6月25日
    00
  • ThinkPHP3.1新特性之多数据库操作更加完善

    关于“ThinkPHP3.1新特性之多数据库操作更加完善”的攻略,主要涉及到以下几个方面: 1. 支持多数据库 在ThinkPHP 3.1中,新增了多数据库支持。在原来的基础上,可以同时连接多个数据库,从而实现对多个数据库的操作。在database.php配置文件中,可以针对不同的数据库配置多个数据库连接参数。示例如下: return array( // 默…

    other 2023年6月27日
    00
  • ASP.Net全局变量的设置和读取方法

    ASP.Net全局变量的设置和读取方法攻略 在ASP.Net中,可以使用Session对象或Application对象来设置和读取全局变量。全局变量可以在整个应用程序中共享和访问。 使用Session对象设置和读取全局变量 Session对象用于在用户会话之间存储和检索数据。以下是设置和读取全局变量的步骤: 设置全局变量: // 在某个页面或事件中设置全局变…

    other 2023年7月29日
    00
  • 深入uCOS中全局变量的使用详解

    深入uCOS中全局变量的使用详解 什么是uCOS中的全局变量? 在uCOS操作系统中,有许多全局变量。它们存储在操作系统的静态存储区域中,对于整个系统而言都是可见的。其中一些全局变量用于保存ucOS的内部状态信息,而另一些则可以由用户自由使用。 全局变量的使用方法 在uCOS系统中,使用全局变量非常简单。要声明一个全局变量,只需在定义该变量的地方使用关键字e…

    other 2023年6月26日
    00
  • excel表格怎么设置打开进入页面布局视图?

    当你打开Excel表格时,默认情况下会进入“普通视图”模式,但你可以通过以下步骤将其更改为“页面布局视图”模式: 打开Excel表格并选择要设置页面布局视图的工作表。 在Excel菜单栏中,点击“视图”选项卡。 在“视图”选项卡中,找到“视图”组,并点击“页面布局”按钮。这将切换到页面布局视图模式。 示例说明1:假设你有一个包含大量数据的工作表,并且你想在打…

    other 2023年9月5日
    00
合作推广
合作推广
分享本页
返回顶部