【专题】堆

来源:互联网 发布:淘宝一个心要多少单 编辑:程序博客网 时间:2024/06/05 02:53

简介

堆结构是一种数组对象,它可以被视为一颗完全二叉树(除了叶子节点别的节点都是满的)。树中结构与数组中存放该节点值得那个元素是对应相同的,见图:

这里写图片描述

堆的性质


设数组A的长度为len,二叉树的节点个数为size,size<=len,则A[i]存储二叉树中编号为i的节点值(1<=i<=size),而A[size]以后的元素并不属于相应的堆,树的根为A[1],并且利用完全二叉树的性质,我们很容易求第i个节点的父节点(prarent(i))、左孩子结点(left(i))、右孩子节点(right(i))的下标了,分别是:i/2、2i、2i+1。
更重要的是,堆具有一个性质,对除根以外的每个节点i,A[parent(i)]>=A[i]。即除根节点外,所有节点的值都不能超过它的父节点,这样就推出,堆中的最大元素存在堆顶,且每个节点的子树中的节点值都咸鱼等于该节点的值,这种堆又称为“大根堆”;反之称为“小根堆”。


堆的操作

up 和 down
up是把一个点移上去的过程。如图:
这里写图片描述
理解一下:
pascal

    procedure up(k:longint);begin        while(k>1)and(a[k]<a[k div 2])do        begin                a[0]:=a[k];                a[k]:=a[k div 2];                a[k div 2]:=a[0];                k:=k div 2;        end;end;

c++

void up(int k){    int now,next;    a[++a_size]=k;    now=a_size;    while (now>1)    {        next=now>>1;        if (a[now]>=a[next]) break;        a[0]=a[k];        a[k]=a[k/2];        a[k/2]=a[0];        now=next;    }}

c++标准模板库STL

void up(int k){    a[++a_size]=k;    //push_a(a+1,a+a_size+1); //大根堆    push_a(a+1,a+a_size+1,greater<int>());//小根堆}

down是把一个点向下移。如下图;
这里写图片描述
理解一下
pascal

procedure down(x:longint);var        y,k:longint;begin        while (x*2<=tot)and(a[x]>a[x*2])or(x*2+1<=tot)and(a[x]>a[x*2+1]) do        begin                y:=x*2;                if(y+1<=tot)and(a[y]>a[y+1])then inc(y);                k:=a[x];                a[x]:=a[y];                a[y]:=k;                x:=y;        end;end;

c++

void down(int k){    int now,next;    now=k;    while (now*2<=a_size)    {        next=now*2;        if (next<a_size&&a[next+1]<a[next]) next++;        if (a[now]<=a[next]) break;        a[0]=a[now];        a[now]=a[next];        a[next]=a[0];        now=nex;    }}

c++标准模板库STL

void down(){    //pop_a(a+1,a+a_size+1);//大根堆    pop_a(a+1,a+a_size+1,greater<int>());//小根堆  }

在堆的应用中,只要好好的运用这两个程序,就会飞啦~~