(二叉)堆

堆可以看成一个近似的完全二叉树,其任何一非叶节点满足性质:

Key[i]<=key[2i+1]&&Key[i]<=key[2i+2](小根堆)

或者

Key[i]>=Key[2i+1]&&key[i]>=key[2i+2](大根堆)

有了上面的定义,就有下面的计算:

#define Pa(i) i>>1 //父亲

#define Le(i) i<<1 //左儿子

#define Ri(i) (i<<1)+1 //右儿子

接下来是维护堆的性质:

一个新的i到堆中。(大根堆)

void Mh(int i){

    int l=Le(i),r=Ri(i),lag;

    if (l<=num && heap[i]<heap[l]) lag=l;

    else lag=i;

    if (r<=num && heap[lag]<heap[r]) lag=r;

    if (lag!=i) {

        swap(heap[i],heap[lag]);

        Mh(lag);

    }

}

实现插入操作:

void Hik(int i,int key){

    heap[i]=key;

    while (i>1 && heap[Pa(i)].d<heap[i].d){

        swap(heap[Pa(i)],heap[i]);

        i=Pa(i);

    }

}

删除最大值:

void Hem(){

    if (num<1) {

        printf("none\n"); return;

    }  

    heap[1]=heap[num];

    num--; Mh(1);

    return;

}

这些是最基本的堆操作,其他操作可以根据这些推出。

但我们一般不手写,因为STL中有priority_queue。

priority_queue<int>que;默认大根堆。

priority_queue<int, vector<int>, greater<int>> que; 小根堆。(#include<functional>//需要用到greater)

struct cmp{

bool operator()(int x, int y){
return x > y; //x越小优先级越高
}
};
priority_queue<int, vector<int>, cmp>que;//这个声明要特别注意两点:vector<int>和cmp

struct node{
int x, y;
friend bool operator<(node a, node b){//标准库默认使用 < 来确认它们的关系,换成>就不行了哦
return a.y>b.y;//>表示越小越优先,<表示越大越优先
} //可以这样记:最大堆与小于号有关,最小堆与大于号有关。这样记会不会好一点呢。。。
};
priority_queue<node> que;

操作:

que.push();

que.top();

que.pop();

还有映射堆:

两个堆互相标记:

来个题吧:

小明的账单

时间限制: 1 Sec  内存限制: 128 MB

题目描述

小明在一次聚会中,不慎遗失了自己的钱包,在接下来的日子,面对小明的将是一系列的补卡手续和堆积的账单。。。 
在小明的百般恳求下,老板最终同意延缓账单的支付时间。可老板又提出,必须从目前还没有支付的所有账单中选出面额最大和最小的两张,并把他们付清。还没有支付的账单会被保留到下一天。 
请你帮他计算出支付的顺序。

输入

第1 行:一个正整数N(N≤15,000),表示小明补办银联卡总共的天数。 
第2 行到第N+1 行:每一行描述一天中收到的帐单。先是一个非负整数M<=100,表示当天 
收到的账单数,后跟M个正整数(都小于1,000,000,000),表示每张帐单的面额。 
输入数据保证每天都可以支付两张帐单。

输出

输出共N 行,每行两个用空格分隔的整数,分别表示当天支付的面额最小和最大的支 
票的面额。

样例输入

4

3 3 6 5

2 8 2

3 7 1 7

0

样例输出

3 6

2 8

1 7

5 7

 1 #include<iostream>
 2 #include<cstdio>
 3 #include<cmath>
 4 #include<cstring>
 5 #include<algorithm>
 6 using namespace std;
 7 #define Pa(i) i>>1
 8 #define Le(i) i<<1
 9 #define Ri(i) (i<<1)+1
10 #define oo 1000000000
11 int size1,size2;
12 struct node{
13     int d,t;
14 } heap_max[2000000],heap_min[2000000];
15 void Max_h(int i){
16     int l=Le(i),r=Ri(i),lag;
17     if (l<=size1 && heap_max[i].d<heap_max[l].d) lag=l;
18     else lag=i;
19     if (r<=size1 && heap_max[lag].d<heap_max[r].d) lag=r;
20     if (lag!=i) {
21         heap_min[heap_max[i].t].t=lag;
22         swap(heap_max[i],heap_max[lag]);
23         return Max_h(lag);
24     }
25 }
26 void Min_h(int i){
27     int l=Le(i),r=Ri(i),lag;
28     if (l<=size2 && heap_min[i].d>heap_min[l].d) lag=l;
29     else lag=i;
30     if (r<=size2 && heap_min[lag].d>heap_min[r].d) lag=r;
31     if (lag!=i) {
32         heap_max[heap_min[i].t].t=lag;
33         swap(heap_min[i],heap_min[lag]);
34         return Min_h(lag);
35     }
36 }
37 void Hik_max(int i,int key){
38     heap_max[i].d=key;
39     while (i>1 && heap_max[Pa(i)].d<heap_max[i].d){
40         heap_min[heap_max[i].t].t=Pa(i);
41         swap(heap_max[Pa(i)],heap_max[i]);
42         i=Pa(i);
43     }
44 }
45 void Hik_min(int i,int key){
46     heap_min[i].d=key;
47     while (i>1 && heap_min[Pa(i)].d>heap_min[i].d){
48         heap_max[heap_min[i].t].t=Pa(i);
49         swap(heap_min[Pa(i)],heap_min[i]);
50         i=Pa(i);
51     }
52 }
53 void Mhi(int a){
54     size1++; heap_max[size1].d=-oo; heap_max[size1].t=size2+1;
55     size2++; heap_min[size2].d=oo; heap_min[size2].t=size1;
56     Hik_max(size1,a); Hik_min(size2,a);
57 }
58 void Hem(){
59     printf("%d %d\n",heap_min[1].d,heap_max[1].d);
60     int mint=heap_max[1].t,maxt=heap_min[1].t;
61     heap_min[mint]=heap_min[size2];
62     size2--; Min_h(1);
63     heap_max[maxt]=heap_max[size1];
64     size1--; Max_h(1);
65     heap_min[1]=heap_min[size2];
66     size2--; Min_h(1);
67     heap_max[1]=heap_max[size1];
68     size1--; Max_h(1);
69     return;
70 }
71 int main()
72 {
73     int n; scanf("%d",&n);
74     while (n--){
75         int nu; scanf("%d",&nu);
76         for (int i=1;i<=nu;i++) {
77             int a; scanf("%d",&a);
78             Mhi(a);
79         }
80         Hem();
81     }
82 }

时间: 2024-10-13 01:48:26

(二叉)堆的相关文章

二叉堆(binary heap)

堆(heap) 亦被称为:优先队列(priority queue),是计算机科学中一类特殊的数据结构的统称.堆通常是一个可以被看做一棵树的数组对象.在队列中,调度程序反复提取队列中第一个作业并运行,因而实际情况中某些时间较短的任务将等待很长时间才能结束,或者某些不短小,但具有重要性的作业,同样应当具有优先权.堆即为解决此类问题设计的一种数据结构. 本文地址:http://www.cnblogs.com/archimedes/p/binary-heap.html,转载请注明源地址. 逻辑定义 n个

算法—二叉堆

实现栈或是队列与实现优先队列的最大不同在于对性能的要求.对于栈和队列,我们的实现能够在常数时间内完成所有操作:而对于优先队列,插入元素和删除最大元素这两个操作之一在最坏情况下需要线性时间来完成.我们接下来要讨论的基于数据结构堆的实现能够保证这两种操作都能更快地执行. 1.堆的定义 数据结构二叉堆能够很好地实现优先队列的基本操作.在二叉堆的数组中,每个元素都要保证大于等于另两个特定位置的元素.相应地,这些位置的元素又至少要大于等于数组中的另两个元素,以此类推.如果我们将所有元素画成一棵二叉树,将每

二叉堆 - 最小堆

二叉堆:一般我们拿来用的就是最大堆和最小堆. 最小堆:每个节点的值比它的左右子节点的值要大. 代码实现如下:参考Mark Allen Weiss<数据结构和算法分析>(第二版) 1 #include <cstdio> 2 #include <cstdlib> 3 4 #define MIN (1<<(sizeof(int)*8-1)) 5 6 typedef int Item; 7 typedef struct HeapStruct* heap; 8 9 s

Bestcoder4——Happy Three Friends(二叉堆)

本文出自:http://blog.csdn.net/svitter Happy Three Friends Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/65536 K (Java/Others) Total Submission(s): 0    Accepted Submission(s): 0 Problem Description Dong-hao , Grandpa Shawn , Beautful-leg

堆排序:什么是堆?什么是最大堆?二叉堆是什么?堆排序算法是怎么样的?PHP如何实现堆排序?

本文标签:  堆排序 php php算法 堆排序算法 二叉堆 数据结构 REST   服务器 什么是堆 这里的堆(二叉堆),指得不是堆栈的那个堆,而是一种数据结构. 堆可以视为一棵完全的二叉树,完全二叉树的一个"优秀"的性质是,除了最底层之外,每一层都是满的,这使得堆可以利用数组来表示,每一个结点对应数组中的一个元素. 数组与堆之间的关系 二叉堆一般分为两种:最大堆和最小堆. 什么是最大堆 堆中每个父节点的元素值都大于等于其孩子结点(如果存在),这样的堆就是一个最大堆 因此,最大堆中的

poj 3253 初涉二叉堆 模板题

这道题很久以前就做过了 当时是百度学习了优先队列 后来发现其实还有个用sort的办法 就是默认sort排序后 a[i]+=a[i-1] 然后sort(a+i,a+i+n) (大概可以这样...答案忘了...) 嗯...其实标准解法是二叉堆.. 主函数里面的while里面wa了好多次.. 每次都选最小的那俩相加 再放回去 #include<stdio.h> #include<string.h> #include<algorithm> using namespace std

在A*寻路中使用二叉堆

接上篇:A*寻路初探 GameDev.net 在A*寻路中使用二叉堆 作者:Patrick Lester(2003年4月11日更新) 译者:Panic 2005年3月28日 译者序:     这一篇文章,是"A* Pathfinding for Beginners.",也就是我翻译的另一篇文章<A*寻路初探>的补充,在这篇文章里,作者再一次展现了他阐述复杂话题的非凡能力,用通俗易懂的语句清晰的解释了容易让人迷惑的问题.还是那句话,如果你看了这篇文章仍然无法领会作者的意图,那

堆、二叉堆、堆排序

堆.二叉堆.堆排序 堆的概念: n个元素序列 { k1, k2, k3, k4, k5, k6 -. kn } 当且仅当满足以下关系时才会被称为堆: ki <= k2i,ki <= k2i+1 或者 ki >= k2i,ki >= k2i+1 (i = 1,2,3,4 .. n/2) 如果数组的下表是从0开始,那么需要满足 ki <= k2i+1,ki <= k2i+2 或者 ki >= k2i+1,ki >= k2i+2 (i = 0,1,2,3 .. n

AC日记——二叉堆练习3 codevs 3110

3110 二叉堆练习3 时间限制: 3 s 空间限制: 128000 KB 题目等级 : 黄金 Gold 题解 题目描述 Description 给定N(N≤500,000)和N个整数(较有序),将其排序后输出. 输入描述 Input Description N和N个整数 输出描述 Output Description N个整数(升序) 样例输入 Sample Input 5 12 11 10 8 9 样例输出 Sample Output 8 9 10 11 12 数据范围及提示 Data Si

codevs 3110 二叉堆练习3

3110 二叉堆练习3 http://codevs.cn/problem/3110/ 题目描述 Description 给定N(N≤500,000)和N个整数(较有序),将其排序后输出. 输入描述 Input Description N和N个整数 输出描述 Output Description N个整数(升序) 样例输入 Sample Input 5 12 11 10 8 9 样例输出 Sample Output 8 9 10 11 12 数据范围及提示 Data Size & Hint 对于3