从零开始手写STL库:Priority_Queue

news/2024/9/28 21:02:36 标签: c++, 开发语言, 学习, stl

从零开始手写STL库–Priority_Queue的实现

Gihub链接:miniSTL


文章目录

  • 从零开始手写STL库–Priority_Queue的实现
  • 一、priority_queue是什么?
  • 二、堆是什么?
  • 三、priority_queue要包含什么函数
  • 总结


一、priority_queue是什么?

优先队列在力扣刷题中可能会出现,实际上就是一个带有权重优先级的队列

在这个队列中,所有元素都会有一个权重,队列会根据权重来对元素排序

这也就是所谓的“优先”,而这个优先顺序是可以自己定义的

对int型优先队列,STL库默认是把数据从大到小排序的

所以难点在于如何排序,答案是基于堆来构建优先队列

那么问题也就明确了,所谓优先队列的考察,实际上是对数据结构–的考察

二、堆是什么?

堆(Heap)是一种特殊的完全二叉树,它满足下面的性质:

结构性质: 堆是一个完全二叉树,这意味着除了最后一层外,每一层都是完全填满的,而最后一层的节点则尽可能地集中在左边。

堆性质: 在一个最大堆(Max Heap)中,每个节点的值都大于或等于其子节点的值,根节点的值是堆中的最大值。相反,在一个最小堆(Min Heap)中,每个节点的值都小于或等于其子节点的值,根节点的值是堆中的最小值。

实际上堆可以用队列实现,不需要真的构建一个二叉树,只需要构建两个维护函数即可

三、priority_queue要包含什么函数

首先明确一下两个维护函数,即向上维护和向下维护

    void heapUp()
    {
        int index = data.size() - 1;
        while (index)
        {
            int parentIndex = (index - 1) / 2;
            if(data[index] > data[parentIndex])
            {
                std::swap(data[index], data[parentIndex]);
                index = parentIndex;
            }
            else break;
        }
    }

    void heapDown() {
        int index = 0;
        int size = data.size();
        while (1) 
        {
            int leftChild = 2 * index + 1;
            int rightChild = 2 * index + 2;
            int largest = index;

            if (leftChild < size && data[leftChild] > data[largest]) largest = leftChild;
            if (rightChild < size && data[rightChild] > data[largest]) largest = rightChild;
            
            if (largest != index) 
            {
                std::swap(data[index], data[largest]);
                index = largest;
            } else break;
        }
    }

本处实现就不考虑string或者其他类型的队列了,只考虑int和double型队列

这里向上向下维护实际上就是堆排序的上浮和下沉

上浮:如果父节点比k结点小,就交换他们的位置
下沉:如果k结点比它的两个子结点小,则与较大的那个交换

之后就是正常的一层双向队列封装,只需要每次插入和删除的时候维护一下堆即可

template <typename T, typename Container = myDeque<T> >
class myPriQue
{
private:
    Container data;

    void heapUp()
    {
        int index = data.size() - 1;
        while (index)
        {
            int parentIndex = (index - 1) / 2;
            if(data[index] > data[parentIndex])
            {
                std::swap(data[index], data[parentIndex]);
                index = parentIndex;
            }
            else break;
        }
    }

    void heapDown() {
        int index = 0;
        int size = data.size();
        while (1) 
        {
            int leftChild = 2 * index + 1;
            int rightChild = 2 * index + 2;
            int largest = index;

            if (leftChild < size && data[leftChild] > data[largest]) largest = leftChild;
            if (rightChild < size && data[rightChild] > data[largest]) largest = rightChild;
            
            if (largest != index) 
            {
                std::swap(data[index], data[largest]);
                index = largest;
            } else break;
        }
    }  

public:
    myPriQue() {};
    myPriQue(const Container & c) : data(c) 
    {
        int size = data.size();
        for(int i = (size / 2) - 1; i >= 0; i --) heapDown();
    }

    void push(const T & value)
    {
        data.push_back(value);
        heapUp();
    }

    void pop()
    {
        if (!data.empty())
        {
            std::swap(data[0], data[data.size() - 1]);
            data.pop_back();
            heapDown();
        }
        else throw std::runtime_error("Stack is empty!");
        
    }

    T& top() 
    {
        if (!data.empty()) return data[0];
        else throw std::runtime_error("Priority queue is empty.");
        
    }

    bool empty()  
    {
        return data.empty();
    }

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

总结

优先队列一般也不会作为考察重点,在力扣中更多地是考虑如何利用vector或者queue自己构建一个专属的优先队列来解决问题,比如单调栈,实际上也是一种优先队列

只需要知道优先队列是以堆为基础构建的即可

至此,简单STL库实现教程完成。由于本人初学,博客中或许会有不对之处,也请读者指出,完整代码异步GitHub链接。


http://www.niftyadmin.cn/n/5681841.html

相关文章

docker安装sonarqube进行代码的质量检测,主要包括语法的检测

注意:下面的操作在安装Jenkins的虚拟机上操作 要在 Docker 中安装 SonarQube,可以使用 Docker Compose 来简化安装过程。以下是详细的步骤和配置: 1. 创建 docker-compose.yml 文件 首先,在一个新的目录中创建一个 docker-compose.yml 文件,内容如下: version: "…

9.26 Buu俩题解

[CISCN2019 华东北赛区]Web2 看wp写完之后写的 知识点 存储型XSS与过滤绕过sql注入 题解 好几个页面&#xff0c;存在登录框可以注册&#xff0c;存在管理员页面(admin.php) ->既然存在管理员页面&#xff0c;且直接访问admin.php提示我们 说明存在身份验证&#xff0…

【Python快速学习笔记01】下载解释器/环境变量配置/PyCharm下载/第一个代码

目录 1.下载python解释器 2.第一个python程序 3.配置解释器环境变量 4.下载开发工具 PyCharm 4.通过PyCharm编写第一个python程序 1.下载python解释器 官网下载&#xff0c;但是下载太慢了&#xff0c;所以直接百度搜了下载了个 Welcome to Python.org 1.官网下载 2.直…

【Kubernetes】日志平台EFK+Logstash+Kafka【理论】

一&#xff0c;日志处理方案 方案一&#xff0c;【EFK】&#xff1a;Elasticsearch Fluentd&#xff08;或Filebeat&#xff09; Kibana Elasticsearch&#xff08;简称&#xff1a;ES&#xff09;&#xff1a;实时&#xff0c;分布式存储&#xff0c;可扩展&#xff0c;日…

亳州自闭症寄宿学校盘点:为孩子打开新世界

在探索特殊教育领域的征途上&#xff0c;每一所学校都是自闭症儿童心灵成长的灯塔&#xff0c;为他们照亮前行的道路。而当我们将目光转向南方繁华的广州&#xff0c;不得不提的是星贝育园自闭症儿童寄宿制学校&#xff0c;这所位于都市之中却充满温情的学校&#xff0c;正以其…

5.3 克拉默法则、逆矩阵和体积

本节是使用代数而不是消元法来求解 A x b A\boldsymbol x\boldsymbol b Axb 和 A − 1 A^{-1} A−1。所有的公式都会除以 det ⁡ A \det A detA&#xff0c; A − 1 A^{-1} A−1 和 A − 1 b A^{-1}\boldsymbol b A−1b 中的每个元素都是一个行列式除以 A A A 的行列式。…

Electron 使用 Nodemon 配置自动重启

在Electron项目中&#xff0c;每次修改了代码都需要手动关闭应用&#xff0c;再执行npm start重启应用。 Nodemon 是一个非常实用的工具&#xff0c;主要用于在开发 Node.js 应用时自动监测文件的变化并重新启动服务器。 安装nodemon 开发环境安装nodemon&#xff1a; npm …

Part_one C语言概述

1.1 编写第一个C程序 1.打开Visual Studio点击"创建新项目" 2.点击"空项目"&#xff0c;并点击"下一步" 3.设置"项目名称"并"设置地址" 4.打开项目后&#xff0c;右击"源文件"并选择"添加"的"新建…