大根堆(模板)

今天学了大根堆,第一次从头到尾个人手打,虽说有些STL能代替堆但效率很低,算了算300000的数据甚至要跑500ms。。。。

也算记录一下吧。

自己的:83ms(300000)

%:pragma GCC optimize(3)
#include<bits/stdc++.h>
#define N 500010
#define INF 0x3f3f3f3f
using namespace std;

struct Heap
{
    int heap[N];
    int size;

void init()
{
    size=0;
}

void adjust_up(int i)//查找父亲节点是否比儿子节点小,如果有,交换,直到没有
{
    int fa=i>>1;
    if(fa<0)
    {
        return ;
    }
    if(heap[i]>heap[fa])
    {
        swap(heap[i],heap[fa]);
        adjust_up(fa);
    }
}

void adjust(int size,int i)//调整父亲和儿子节点,以保证父亲节点一定大于儿子
{
    int ls,rs,maxa;
    ls=i<<1;
    rs=i<<1|1;
    if(ls<=size&&heap[ls]>heap[i])
    {
        maxa=ls;
    }
    else
    {
        maxa=i;
    }
    if(rs<=size&&heap[rs]>heap[maxa])
    {
        maxa=rs;
    }
    if(heap[maxa]!=heap[i])
    {
        swap(heap[maxa],heap[i]);
        adjust(size,maxa);
    }

}

void push(int x)
{
    heap[size]=x;
    adjust_up(size);
    size++;
}

int top()
{
    return heap[0];
}

void pop()
{
    swap(heap[0],heap[size]);
    size--;
    adjust(size,0);
}

bool empty()
{
    if(size<0)
    {
        return true;
    }
    return false;
}

};

int main()
{
    double time1;
    int i,j;
    srand(time(NULL));
    Heap my_heap;
    my_heap.init();
    clock_t startTime,endTime;
    startTime = clock();
    for(i=1;i<=300000;i++)
    {
        int x=rand()*rand();
        my_heap.push(x);
    }
    my_heap.size--;
    while(!my_heap.empty())
    {
        //printf("%d ",my_heap.top());
        my_heap.pop();
    }

    endTime = clock();
    time1=(double)(endTime - startTime) / CLOCKS_PER_SEC;
    printf("%.6lf",time1);
    return 0;
}

老师的:71ms(300000)

#include <bits/stdc++.h>
using namespace std;

const int N = 300000;

struct Heap {
    int heap[N + 10];
    int size;

    void init() {
        size = 1;
    }

    void push (int x) {
        int i = size++;
        while (i > 1) {
            int p = (i >> 1);
            if (heap[p] > x) {
                break;
            }
            heap[i] = heap[p];
            i = p;
        }
        heap[i] = x;
    }

    int pop() {
        int ret = heap[1];
        int x = heap[--size];

        int i = 1;
        while ((i << 1) < size) {
            int lson = (i << 1);
            int rson = (i << 1 | 1);
            if (rson < size && heap[rson] > heap[lson]) lson = rson;

            if (heap[lson] < x) {
                break;
            } 

            heap[i] = heap[lson];
            i = lson;
        }
        heap[i] = x;
        return ret;
    }

    bool empty() {
        return size == 0;
    }
};

int a[N];

int main () {

    srand(time(NULL));

    Heap my_heap;
    my_heap.init();
    for (int i = 0; i < N; i++) {
        a[i] = rand()*rand();
    }

//start here
    clock_t mystart = clock();
    for (int i = 0; i < N; i++) {
        my_heap.push(a[i]);
    }

    while(!my_heap.empty()) {
        my_heap.pop();
    }

    clock_t myend = clock();
//end here

    priority_queue<int> heap;

    clock_t start = clock();
    for (int i = 0; i < N; i++) {
        heap.push(a[i]);
    }

    while(!heap.empty()) {
       // cout << heap.top() << endl;
        heap.pop();
    }

    clock_t end = clock();
    cout << "Running time of xjoi machine is:" << static_cast<double> (myend-mystart)/CLOCKS_PER_SEC*1000 << "ms" << endl;
    cout << "Running time stl is:" << static_cast<double> (end-start)/CLOCKS_PER_SEC*1000 << "ms" << endl;

    return 0;
}

每天刷题身体棒棒!

时间: 2024-08-07 04:13:45

大根堆(模板)的相关文章

大根堆

2017-07-24 22:04:08 writer:pprp 参考书目:张新华的<算法竞赛宝典> 思路跟小根堆一个样,主要的思路是先构造一个大根堆,然后在每次将最大的一个排除出来,再进行堆排序 代码如下: #include <iostream> using namespace std; const int maxn = 100; int a[maxn],n,heapsize; void maxheapify(int i) //根据数组的下表对应节点,对其左右两个子节点进行堆构造:

hdu 4857 逆拓扑+大根堆(priority_queue)

题意:排序输出:在先满足定约束条件下(如 3必需在1前面,7必需在4前面),在满足:1尽量前,其次考虑2,依次.....(即有次约束). 开始的时候,只用拓扑,然后每次在都可以选的时候,优先考虑小的,其实没什么简单,如 图(3-->1,2)这样输出是2.3.1,正确应该是 3 1 2,因为 1要尽量前(都满足第一约束). 参考他人思路结合自己理解:因为这样的弊端就是没有考虑这种情况:图中:若我的"子孙"中,有的比你次优先,虽然现在我们都可以输出,但是要考虑我的子代,若我的子代有次

Java实现堆排序(大根堆)

堆排序是一种树形选择排序方法,它的特点是:在排序的过程中,将array[0,...,n-1]看成是一颗完全二叉树的顺序存储结构,利用完全二叉树中双亲节点和孩子结点之间的内在关系,在当前无序区中选择关键字最大(最小)的元素. 1. 若array[0,...,n-1]表示一颗完全二叉树的顺序存储模式,则双亲节点指针和孩子结点指针之间的内在关系如下: 任意一节点指针 i:父节点:i==0 ? null : (i-1)/2  左孩子:2*i + 1  右孩子:2*i + 2 2. 堆的定义:n个关键字序

堆排序—大根堆,小根堆

1.小根堆 若根节点存在左子女则根节点的值小于左子女的值:若根节点存在右子女则根节点的值小于右子女的值. 2.大根堆 若根节点存在左子女则根节点的值大于左子女的值:若根节点存在右子女则根节点的值大于右子女的值. 3.结论 (1)堆是一棵完全二叉树(如果公有h层,那么1~h-1层均满,在h层连续缺失若干个右叶子). (2)小根堆的根节点的值是最小值,大根堆的根节点的值是最大值. (3)堆适合于采用顺序存储. 4.堆的插入算法 将一个数据元素插入到堆中,使之依然成为一个堆. 算法描述:先将结点插入到

bzoj4919: 大根堆

Description 给定一棵n个节点的有根树,编号依次为1到n,其中1号点为根节点.每个点有一个权值v_i. 你需要将这棵树转化成一个大根堆.确切地说,你需要选择尽可能多的节点,满足大根堆的性质:对于任意两个点i,j,如果i在树上是j的祖先,那么v_i>v_j. 请计算可选的最多的点数,注意这些点不必形成这棵树的一个连通子树. Input 第一行包含一个正整数n(1<=n<=200000),表示节点的个数. 接下来n行,每行两个整数v_i,p_i(0<=v_i<=10^9

大根堆pop push详细注释

//大根堆procedure push(x:longint);//元素x入堆 O(log t)var  tx,i:longint;begin  inc(t);//堆顶top加1  a[t]:=x;//将x放入堆的最后一个节点  i:=t;  while (i>1)and(a[i>>1]<a[i]) do//将元素x一层一层向上传递直到 到达根或上一层大于本身<=>找到x应在的位置    begin    tx:=a[i>>1];     a[i>>

poppo大根堆的原理与实现。

大根堆的定义:1 大根堆是一个大根树 2 大根堆是一个完全二叉树 所以大根堆用数组表示是连续的,不会出现空白字段. 对于大根堆的插入 对于大根堆的插入,可以在排序前确定大根堆的形状,可以确定元素5从位置6插入,那么比较元素5和位置3的元素2, 元素5比元素2大,将2下移.接着比较元素5和元素20,一次类推,直到找到元素5的合理位置. 接着看一下如果插入的元素是21,怎么进行排序. 21比2大,所以将2下移,接着比较21和20,发现20比21小,20下移,最终21放到 根的位置.形成大根堆. 对于

大根堆的创建过程

初始堆就是大根堆,只是是第一次(初始序列)调整,第一次必须是自底向上逐个调整,以后(第一次交换后)是自上向下调整(因为除了第一个即堆顶元素,其他都是已经调整好的堆).过程:先把数据画出一颗二叉树:                     40           30                92    16         20     47       25 56   55  35从最后一个数据的双亲(20)开始,数据最大的成为双亲20和35交换:下一个双亲(16),16和56交换:双

序列——堆排序-大根堆(堆大顶)

1.小根堆 如果根是儿童的存在留下的根值左孩子小于值:如果根是儿童的权利的存在的根值比他们的孩子的权利少值. 2.大根堆 如果根是儿童的存在留下的根值多名离开自己的孩子值.子女则根节点的值大于右子女的值. 3.结论 (1)堆是一棵全然二叉树(假设公有h层,那么1~h-1层均满,在h层连续缺失若干个右叶子). (2)小根堆的根节点的值是最小值,大根堆的根节点的值是最大值. (3)堆适合于採用顺序存储. 4.堆的插入算法 将一个数据元素插入到堆中,使之依旧成为一个堆. 算法描写叙述:先将结点插入到堆