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日

相关文章

  • 22点关于jquery性能优化的建议

    22点关于jQuery性能优化的建议 jQuery是一个功能强大的JavaScript库,但在处理大型项目或复杂页面时,性能可能成为一个问题。下面是22个关于jQuery性能优化的建议,帮助你提高网页的加载速度和响应性。 1. 使用最新版本的jQuery 始终使用最新版本的jQuery,因为每个版本都会修复一些性能问题和错误。 2. 使用压缩版本的jQuer…

    other 2023年7月29日
    00
  • Win7系统遇到IE加载项故障的原因及两种解决办法

    Win7系统遇到IE加载项故障的原因及两种解决办法 问题原因 Win7系统在使用IE浏览器时,可能会出现加载项故障的情况,这种情况可能是由以下原因造成的: IE浏览器本身的问题; 某些加载项的问题; 系统文件损坏。 解决方法 方法1:修复IE浏览器 如果IE浏览器本身出现问题,可以采用以下步骤进行修复: 点击Start菜单,选择Control Panel。 …

    other 2023年6月25日
    00
  • sqllite更新一个表的2个字段到另一个表的2个字段

    以下是“SQLite更新一个表的2个字段到另一个表的2个字段”的完整攻略: SQLite更新一个表的2个字段到另一个表的2个字段 在SQLite,可以使用UPDATE语句来更新表的数据。本攻略将介绍如何使用UPDATE语句将一个表的2个字段更新到另一个表的个字段。 更新一个表2个字段到另一个表的2个字段 以下是使用UPDATE语句将一个表的2个字段更新到另一…

    other 2023年5月7日
    00
  • 什么是深度学习?

    深度学习是机器学习的一种分支,使用多层神经网络模型进行特征提取和模型训练,以解决复杂的分类和预测问题。深度学习可以应用于图像识别、语音识别、自然语言处理等领域,在人工智能领域中具有重要的地位。 深度学习的完整攻略可以按照以下步骤进行: 数据准备在进行深度学习之前,首先需要准备好数据集。通常情况下,数据集需要包含大量的数据样本,并且需要进行标注。常用的公开数据…

    其他 2023年4月19日
    00
  • 机器学习-学习笔记(一)–>(假设空间&版本空间)及归纳…

    机器学习-学习笔记(一)–>(假设空间&版本空间)及归纳学习算法 引言 机器学习是人工智能和数据科学领域的热点话题。本篇文章旨在介绍机器学习中的重要概念——假设空间和版本空间,以及一个常用的归纳学习算法——Find-S 算法。 假设空间和版本空间 假设空间是指机器学习模型能够表示的所有可能假设的集合。在监督学习中,每个假设由一个函数表示,即假…

    其他 2023年3月28日
    00
  • Java数组的基本学习教程

    Java数组的基本学习教程 什么是Java数组? Java中的数组是一个存储固定大小的相同类型元素的有序集合。它们是使用相同名字和类型的变量的一组变量。 如何声明一个数组? 可以使用以下语法声明一个Java数组: type[] arrayName; 其中type是数据类型,如int、float、double等,arrayName是数组名。 例如,声明一个包含…

    other 2023年6月25日
    00
  • vue-cli4使用全局less文件中的变量配置操作

    Vue-cli4使用全局less文件中的变量配置操作攻略 在Vue-cli4中,我们可以使用全局的Less文件来配置变量,以便在整个项目中共享这些变量。下面是详细的步骤: 步骤一:安装依赖 首先,我们需要安装less和less-loader依赖。在项目根目录下打开终端,执行以下命令: npm install less less-loader –save-d…

    other 2023年7月29日
    00
  • 影音先锋如何下载电影(查看已下载的电影目录)

    影音先锋如何下载电影(查看已下载的电影目录) 影音先锋是一款流行的多媒体播放器,同时也提供了电影下载功能。下面是影音先锋下载电影的完整攻略,包括查看已下载的电影目录。 下载电影 首先,确保你已经安装了最新版本的影音先锋软件。你可以从官方网站或其他可信的软件下载网站下载并安装。 打开影音先锋软件。在主界面上,你会看到一个搜索框。 在搜索框中输入你想要下载的电影…

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