堆--优先队列

来源:互联网 发布:手机噪音检测软件 编辑:程序博客网 时间:2024/06/06 01:31

1.完全二叉树的一个父节点编号为k,那么他的左二子的编号为2*k,右二子节点的编号为2*k+1

2.如果已知儿子(左儿子或者右儿子)的编号为x,那么他的父节点的编号为x/2(取整除,就是计算机里的/)

3.一棵完全二叉树的高度为logN,即最多有logN层节点

4.最小堆是所有的父节点都比他的子节点小,最大堆是所有的父节点都比他的子节点大


5.像这样支持插入元素和寻找元素(最大值和最小值)的数据结构成为优先队列,如果使用普通队列,那么寻找最大元素就需要枚举整个队列,时间复杂度为O(n),时间复杂度比较高,如果是已经排好序的数组,那么插入一个元素需要移动大量的数据,时间复杂度依旧很高,而堆就是一种优先队列的实现,可以很好地解决这两种操作


6.堆经常被用来求一个数列中第K大的数,只需要建立一个大小为K的最小堆,堆顶就是第K大的数(举个例子,假设有事十个数,要求第3大的数,将前三个数建成最小堆,然后从第四个数开始,与堆顶元素比较,如果比堆顶元素大,则舍弃当前堆顶元素,而将这个新数作为堆顶,然后堆顶开始向下调整,如果比堆顶元素小,则不进入堆),同理如果求第K小的数,那么就建一个最大堆,这种方法的时间复杂度为O(NlogK)

<span style="font-size:18px;">//该算法用来把数从小到大排序#include<iostream>#include<queue>#include<stack>#include<cstdio>#include<string>#include<cstring>#include<algorithm>#define maxn 20#define inf 0x3f3f3f3fusing namespace std;int h[maxn];//用来存放堆的数组int n;//用来存储堆中元素的个数,也就是堆的大小//交换堆中两个元素的位置void swap(int i, int j){    int t=h[i];    h[i]=h[j];    h[j]=t;    return;}void siftdown(int i)//从i开始向下调整{    int t,flag=1;    while(i*2<=n && flag)//至少存在左儿子    {        if(h[i*2]>h[i])            t=i*2;        else t=i;                if(i*2+1<=n)//如果存在右儿子        {            if(h[i*2+1]>h[t])                t=i*2+1;        }                if(i!=t)//说明父节点不是最小的点        {            swap(i,t);//交换父节点和比父节点大的子节点的位置            i=t;//更新为刚才交换的子节点的编号,方便继续向下调整        }        else            flag=0;    }    return;}void creat(){    for(int i=n/2;i>=1;i--)//从最后一个父节点开始向下调整        siftdown(i);}void heapsort(){    while(n>1)    {        swap(1,n);        n--;        siftdown(1);    }    return;}int main(){    int num;    scanf("%d",&n);    for(int i=1;i<=n;i++)        scanf("%d",&h[i]);    num=n;    creat();//建堆    heapsort();//堆排序    printf("\n");    for(int i=1;i<=num;i++)        printf("%d ",h[i]);    printf("\n");        return 0;        }/*输入数据 14 99 5 36 7 22 17 46 12 2 19 25 28 1 92 输出结果 1 2 5 7 12 17 19 22 25 28 36 46 92 99 */</span>


0 0
原创粉丝点击