优先队列

堆 堆排序 优先队列 图文详解(Golang实现)

ぐ巨炮叔叔 提交于 2019-12-06 08:25:20
引入 # 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 # 举例 # 如上图所示,就为一个最小堆。 特性 # 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 # 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 Copy 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 # Copy // 本例为最小堆 // 最大堆只需要修改less函数即可 type

堆 堆排序 优先队列 图文详解(Golang实现)

扶醉桌前 提交于 2019-12-05 22:17:04
引入 在实际应用中,我们经常需要从一组对象中查找 最大值 或 最小值 。当然我们可以每次都先排序,然后再进行查找,但是这种做法效率很低。哪么有没有一种特殊的数据结构,可以高效率的实现我们的需求呢,答案就是 堆(heap) 堆分为最小堆和最大堆,它们的性质相似,我们以最小堆为例子。 最小堆 举例 如上图所示,就为一个最小堆。 特性 是一棵完全二叉树 如果一颗二叉树的任何结点,或者是树叶,或者左右子树均非空,则这棵二叉树称做满二叉树(full binary tree) 如果一颗二叉树最多只有最下面的两层结点度数可以小于2,并且最下面一层的结点都集中在该层最左边的连续位置上,则此二叉树称做完全二叉树(complete binary tree) 局部有序 最小堆对应的完全二叉树中所有结点的值均不大于其左右子结点的值,且一个结点与其兄弟之间没有必然的联系 二叉搜索树中,左子 < 父 < 右子 存储结构 由于堆是一棵完全二叉树,所以我们可以用顺序结构来存储它,只需要计算简单的代数表达式,就能够非常方便的查找某个结点的父结点和子节点,既避免了使用指针来保持结构,又能高效的执行相应操作。 结点i的左子结点为2xi+1,右子结点为2xi+2 结点i的父节点为(i-1)/2 数据结构 // 本例为最小堆 // 最大堆只需要修改less函数即可 type Heap []int func (h Heap)

PriorityQueue源码分析

↘锁芯ラ 提交于 2019-12-05 01:31:50
PriorityQueue是从JDK1.5开始提供的新的数据结构接口,它是一种基于 优先级堆 的极大优先级队列。优先级队列是不同于先进先出队列的另一种队列。每次从队列中取出的是具有最高优先权的元素。如果不提供Comparator的话,优先队列中元素默认按自然顺序排列,也就是数字默认是小的在队列头,字符串则按字典序排列,也可以根据 Comparator 来指定,这取决于使用哪种构造方法。优先级队列不允许 null 元素。依靠自然排序的优先级队列还不允许插入不可比较的对象(这样做可能导致 ClassCastException) 优先级队列是无界的,但是有一个内部容量,控制着用于存储队列元素的数组大小。它通常至少等于队列的大小。随着不断向优先级队列添加元素,其容量会自动增加。无需指定容量增加策略的细节。 我们从源码的角度来看看 PriorityQueue是如何实现的。 建堆: PriorityQueue内部的数组声明如下: private static final int DEFAULT_INITIAL_CAPACITY = 11; /** * Priority queue represented as a balanced binary heap: the two * children of queue[n] are queue[2*n+1] and queue[2*(n+1)].

【LeetCode解题总结】栈/队列篇

丶灬走出姿态 提交于 2019-12-04 13:29:59
基础数据结构 栈 特点 栈的最大特点就是后进先出(LIFO)。对于栈中的数据来说,所有操作都是在栈的顶部完成的,只可以查看栈顶部的元素,只能够向栈的顶部压⼊数据,也只能从栈的顶部弹出数据。 实现 利用一个单链表来实现栈的数据结构。而且,因为我们都只针对栈顶元素进行操作,所以借用单链表的头就能让所有栈的操作在 O(1) 的时间内完成。 应用场景 在解决某个问题的时候,只要求关心最近一次的操作,并且在操作完成了之后,需要向前查找到更前一次的操作。 队列 特点 和栈不同,队列的最大特点是先进先出(FIFO),就好像按顺序排队一样。对于队列的数据来说,我们只允许在队尾查看和添加数据,在队头查看和删除数据。 实现 可以借助双链表来实现队列。双链表的头指针允许在队头查看和删除数据,而双链表的尾指针允许我们在队尾查看和添加数据。 应用场景 直观来看,当我们需要按照一定的顺序来处理数据,而该数据的数据量在不断地变化的时候,则需要队列来帮助解题。在算法面试题当中,广度优先搜索(Breadth-First Search)是运用队列最多的地方。 常见解题思路 栈 注意事项 出栈前要判空 考虑将什么东西压栈 考虑什么条件下压栈与出 解法总结 高级数据结构 双端队列 特点 双端队列和普通队列最大的不同在于,它允许我们在队列的头尾两端都能在 O(1) 的时间内进行数据的查看、添加和删除。 实现 与队列相似

P1090 合并果子

只谈情不闲聊 提交于 2019-12-04 02:30:36
这道题用哈夫曼树做,使用STL中的优先队列。 优先队列: #include <queque> //升序 priority_queuqe <int,vector<int>,greater<int> > q; //在q前面需要空一格,否则就是右移. priority_queque <int,vector<int>,less<int> >q; //降序,也可不写,默认。 q.push(a) //将a压入栈 q.top() ;//取出栈顶元素 q.pop(); //栈顶指针减一。 q.size() ;//队列中有几个元素。 原理思想是:当一直在合并两个最小堆时消耗值最小,所以就是用哈夫曼树,因为一直是最小的,所以最后算的值也最小。 1 #include <iostream> 2 #include <cstdio> 3 #include <queue> 4 using namespace std; 5 //使用优先队列完成,使用到霍夫曼数 6 int n; 7 const int MAXN=10000; 8 int a[MAXN]; 9 int main() 10 { 11 priority_queue <int,vector<int>,greater<int> >q; //必须加上gteater<int> 12 scanf("%d",&n); 13 int sum=0; 14 for

优先队列(一)——二叉堆

十年热恋 提交于 2019-12-04 01:39:36
二叉堆的抽象数据类型: 1 #ifndef _BinHeap_H 2 #define ElementType int 3 #define MinElement -1000 4 struct HeapStruct; 5 typedef struct HeapStruct *PriorityQueue; //结构体指针 6 PriorityQueue Initialize(int MaxElements); //初始化一个二叉堆 7 void Destroy(PriorityQueue H); //销毁二叉堆的操作 8 void MakeEmpty(PriorityQueue H); //置空一个二叉堆的操作 9 void Insert(ElementType X, PriorityQueue H); //插入操作 10 ElementType DeleteMin(PriorityQueue H); //删除最小元的操作 11 ElementType FindMin(PriorityQueue H); //找到最小元的操作 12 int IsEmpty(PriorityQueue H); //判断二叉堆是否为空的操作 13 int IsFull(PriorityQueue H, int MaxElement); //判断二叉堆是否已满的操作 14 PriorityQueue

[模板]Dijkstra-优先队列优化-单元最短路

人走茶凉 提交于 2019-12-04 01:06:19
输入: 6 9 1 1 2 1 1 3 12 2 3 9 2 4 3 3 5 5 4 3 4 4 5 13 4 6 15 5 6 4 输出: 0 1 8 4 13 17 Code: 1 #include<iostream> 2 #include<cstring> 3 #include<queue> 4 using namespace std; 5 #define PII pair<int,int> 6 const int maxn=10000,maxm=1000; 7 int cnt=0,edge[maxm],ver[maxm],nxt[maxm],head[maxn]; 8 int d[maxn]; 9 bool v[maxn];//v[i]表示i点是否松弛 10 priority_queue < PII,vector<PII>,greater<PII> > q;//优先队列,以p.first最小优先 11 inline void add(int x,int y,int z) 12 { 13 cnt++; 14 ver[cnt]=y; 15 edge[cnt]=z; 16 nxt[cnt]=head[x]; 17 head[x]=cnt; 18 } 19 inline void dijk(int t) 20 { 21 int i; 22 memset(d,0x3f,sizeof

数据结构——优先队列

丶灬走出姿态 提交于 2019-12-03 17:02:47
2019-11-06 10:43:47 参考《数据结构与算法分析 C++描述》 优先队列的应用: 操作系统的进程调度:MLFQ(多级反馈队列) 模型: 优先队列至少满足两种操作:1.插入 (insert) 2. deleteMin(删除最小顶) 如同大多数数据结构一样,有时可能要添加一些其他的操作,但这些添加的操作属于扩展的操作,而不是基本模型的一部分。 实现方法: 1.链表 2.二叉查找树 来源: https://www.cnblogs.com/JasonPeng1/p/11803893.html

题解:2018级算法第三次上机 C3-Zexal的浩瀚星辰

孤街浪徒 提交于 2019-12-03 05:31:29
题目描述: 样例: 实现解释: 一道结合了火箭发射的贪心题目 知识点: 贪心,优先队列 题目分析: 根据题目描述可知,延迟后时间是正常推进的,也就是假设共有 n 个火箭,推迟 k 小时。则在到达 k+1 小时时,每过一个小时只要火箭没发射完都会有 k (如果 k 大于 n 就是有剩余数量)个火箭会遭受延迟的损失,显然这是必然的(因为到达 k 小时前的损失都已经确定了,无法改变)。 那么依据题意只要使得每次这 k 个火箭的损失最小即可,而如何最小:让其中单位时间损失最大的火箭发射即可,这样一定比发射其他火箭的损失要小。 于是便可得出贪心的状态转移方程: cost[i] = cost[i-1]+sum ( sum 既是此时除去最大损失火箭的总损失量) sum 的获取可以利用排序实现,不过考虑到时间问题,还是用优先队列进行最好,边输入边处理便可解决,具体实现可参考完整代码,内含注释。 难点: 即如何获得当前状态的 sum ,常规来说只需去除损失最大的火箭然后遍历剩余的相加即可。一次优化:利用 sum 数组和 out 变量提前存储避免遍历,不过还是需要排序;二次优化:利用优先队列获取最大值,免去排序。 完整代码: #include<iostream> #include<cstring> #include<queue> using namespace std; //考虑到数据范围

C++ 优先队列 priority_queue

孤街浪徒 提交于 2019-12-03 02:41:00
平时定义的时候,直接上就完事了: priority_queue<int>Q; 默认大根堆。 之前很菜的时候不知道小根堆怎么写,还在考场上干过加个负号甩到大根堆里面去的蠢事。 它的完整形式呢,其实是长这个样子的: //小根堆 priority_queue <int,vector<int>,greater<int> > Q; //大根堆 priority_queue <int,vector<int>,less<int> >Q; 然后就是一些特殊的情况: 用pair的时候,先按first,再按second 自动排序 。 priority_queue<pair<int,int> >Q; 如果要自定义排序的话,可以写一个$cmp$: struct node{ int a,b; }num[N]; struct cmp { bool operator()(const int &p,const int &q) { if(num[p].b<num[q].b) return 1; else return 0; } }; priority_queue<int,vector<int>,cmp> Q; To be continue... 来源: https://www.cnblogs.com/lyttt/p/11774367.html