当前位置: 首页 > article >正文

使用C++构建一个优先级队列

1.优先级队列的介绍

   优先级队列是一种特殊的队列数据结构,它是队列,但又不完全是,因为它要将装载的数据进行优先级排序,找到一个最大或者最小优先级的元素,下一次出队列的元素就是这个元素,所以说它不完全是一个队列,优先级队列广泛应用于任务调度、资源分配、事件处理、Dijkstra算法、A*搜索算法等领域。

2.优先级队列的设计

 个人感觉,设计一个优先级队列就是一个堆建立和调整的过程,因为要装载元素,所以我们采用vector来作为成员变量,后续就是对与这个vector变量的管理就行了,因为我们只是简单设计一个优先级队列,所以并没有设计在优先级队列中传入函数进行比较的过程,只是简单的比较大小的过程,首先我们要设计向上调整函数和向下调整函数,因为这个的构造函数和析构函数非常简单,这里我就不过多赘述了。

向上调整函数

向上调整函数就是子节点与父节点做比较,这里我们假设建小堆,如果子节点小于父节点,那么这个堆就是有问题的,所以要进行交换,将子节点与父节点进行交换,但是我们又要考虑交换以后得子节点也就是现在的父节点是否和他现在的父节点又是不对的关系的,所以我们要进行循环,只有当节点为0,也就是根节点或者,子节点小于父节点时,进行循环退出

void siftUp(size_t index)
{
    
    while (index > 0)
    {
        int father = index / 2;
        
        if (list[father] > list[index])
        {
            swap(list[father], list[index]);
            index = father;
        }
        else
        {
            break;
        }
    }
}

向下调整函数

向下调整就是判断你是否比你的两个孩子都要小,逻辑和向上调整函数差不多,只是要和两个孩子都比一次,或者找最小的那个孩子比,主要是要知道孩子是index/2-1和index/2-2就行

void siftDown(size_t index)
{
    while (index <= list.size())
    {
        leftson = index * 2 + 1;
        rightson = index * 2 + 2;
        if (list[index] > list[leftson])
        {
            swap(list[index], list[leftson])
                index = leftson;
        }
        else if (list[index] > list[rightson])
        {
            swap(list[index], list[rightson]);
            index = rightson;
        }
        else
        {
            break;
        }
    }
}

建堆函数

在构造函数的第一步肯定是拷贝构造对应的vector,然后得到的这个vector大概率不是一个堆,因此要对它进行调整,使得它可以成为一个符合规则的堆,一般建堆有两种策略,一种是自下而上的sift down方法,另一种是自上而下的sift up方法。这里我们使用sit down 向下调整的方法,找到最后一个非叶子节点,也就是list.size()/2,然后对每个非叶子节点进行向下调整

explicit Heap(const std::vector<T>& array)
    :list(array)
{
    buildHeap();
}
void buildHeap()
{
    for (int i = list.size() / 2 ; i >=0  ; i--)
    {
        siftDown(i);
   }
}

插入函数

当我们插入一个元素时,我们首先是尾插入vector列表,然后对这个元素进行向上调整,就使得这个堆变得规则

void insert(const T& value)
{
    list.insert(value);
    siftUp(list.size() - 1);
}

获取顶端元素函数

我们建立这个堆或者说维护这个优先级队列肯定是为了得到一个有价值的元素,所有这个堆里面最有价值的元素当然时堆顶元素,但是当我们得到堆顶元素时,这个堆也会被破坏,所以,我们一般会将堆顶元素和最后一个元素进行交换,然后再对堆顶元素进行向下调整,就让堆保持合适的规则

void removeTop()
{
    if (list.empty()) {
        throw std::out_of_range("Heap is empty");
    }
    swap(list[0], list[list.size() - 1]);
    siftDown(0);
    list.erase(list.end() - 1);
}


http://www.kler.cn/a/533235.html

相关文章:

  • C#属性和字段(访问修饰符)
  • 使用开源项目:pdf2docx,让PDF转换为Word
  • 【高级篇 / IPv6】(7.2) ❀ 05. 在60E上配置ADSL拨号宽带上网(IPv6) ❀ FortiGate 防火墙
  • Java 大视界 -- Java 大数据在智能医疗影像诊断中的应用(72)
  • 神经网络参数量和运算量的计算- 基于deepspeed库和thop库函数
  • 【数据分析】案例04:豆瓣电影Top250的数据分析与Web网页可视化(numpy+pandas+matplotlib+flask)
  • 代理模式的作用
  • 从 DeepSeek R1 中提取数学推理数据,使用 CAMEL
  • 华为手机nova9,鸿蒙系统版本4.2.0.159,智慧助手.今天版本是14.x,如何卸载智慧助手.今天?
  • Python进行模型优化与调参
  • SGlang 专为大模型设计的高效服务框架
  • DRGDIP 2.0时代下基于PostgreSQL的成本管理实践与探索(上)
  • AI透明化与全球政治格局的发展:如何避免AI被人为操控
  • 电商用户画像数据可视化分析
  • 基于MODIS/Landsat/Sentinel/国产卫星遥感数据与DSSAT作物模型同化的作物产量估算
  • 使用 Redisson 实现分布式并发限流
  • Spring 面试题【每日20道】【其三】
  • 力扣73矩阵置零
  • 【Leetcode 每日一题】541. 反转字符串 II
  • Vue3 完整学习笔记 - 第二部分
  • Vue.js组件开发-实现广告图片浮动随屏幕滚动
  • LeetCode:115.不同的子序列
  • C++实现有限元三维杆单元计算 Bar3D2Node类(纯自研 非套壳)
  • 在 Ubuntu 22.04 上运行 Filebeat 7.10.2
  • vue2语法速通
  • 猫眼Java开发面试题及参考答案(上)