堆以及堆的相关应用

来源:互联网 发布:做flash的软件 编辑:程序博客网 时间:2024/06/01 10:21

堆简介:

本文中的堆是一种树形数据结构,可以把堆看成一种特殊的完全二叉树,再从二叉树上加上一些限制条件即可以构成堆。即要求父节点元素全部都大于或等于子节点元素,或者小于等于。
这就构成了俩种堆:

  • 1.大根堆:A[PARENT[i]] >= A[i]

  • 2.小根堆:A[PARENT[i]] <= A[i]

堆的常见应用为:

  1. 使用堆进行排序,也就是常说的堆排序,时间复杂度为nlgn(这是比较排序时间复杂度的下限,即使用比较的排序方法,时间复杂度不可能比这个更低了)。其具体的做法是利用大根堆(假设此时堆的元素个数尾heapsize-1),每次把堆顶元素和堆尾元素表交换,那么最大的元素就再堆尾了,这就算确定了一个元素的最终位置,然后再把新的包含heapsize-1个元素的堆进行位置调整,因为之前的调换有可能破坏的堆。这个过程迭代到堆元素为0即结束,此时元素已经排序好了。
  2. 实现最大优先队列,优先队列是一种用来维护元素构成集合S的数据结构,一个最大优先队列支持一下操作
    1.insert(S,x) 把x插入结合S
    2.maxmum(S),返回S中关键字最大的元素
    3.Extractmax(S),返回并且删除S中关键字最大的元素。
    4.incresment-key(S,x,k),把元素x的关键字增加到k,这里假设k不小于x的原关键字值。 最大优先队列的应用很多,其中一个就是共享计算机的作业调度,对打优先队列记录各个作业之间的优先级,当一个作业完成或者被中断时,调用extreacmax从等待作业中选出优先级最高的执行,在任何时候都可以调用insert来插入一个作业。

  3. 实现最小优先队列,主要用在事件调度的模拟器。

说完了堆的基本概念和应用,下面我们来看你看堆具体怎么实现。
再次我们用数组实现堆,首先再一棵二叉树中加入根的位置是i(数组从1开始,0号单元不用)那门其左子输的位置就为2×i,右子树的位置为2×i+1.其父节点的位置就为i/2.把这些关系写成函数有:
int parent(int i){ //得到节点i的父节点
return i/2;
}
int right(int i){ //得到节点i左孩子
return 2*i+1;
}
int left(int i){ //得到节点i的右孩子
return 2*i;
}
我们把建堆的步骤分解:

  1. max_heap维护堆的性质。
    给定一个节点A[i]找出其左右子节点和A[i]三个数的最大值,把A[i]和最大值调换,对于调换过的节点,递归实现此过程。
  2. build_max_heap从后往前维护堆的性质,当这个过程完成以后,整个堆就建立了。
    对所有非叶子节点实现max_heap过程即可建立一个堆。 下面给出堆排序具体实现其中包含了建堆以及排序:
#include<stdio.h>int parent(int i){        return i/2;}int right(int i){        return 2*i+1;}int left(int i){        return 2*i;}int heapsize=10;//维护堆的性质void max_heap(int A[],int i,int heapsize){         int l=left(i);        int r=right(i);        int largest=i;        if(l<=heapsize&&A[l]>A[i])                largest=l;        if(r<=heapsize&&A[r]>A[largest])                largest=r;        if(largest!=i){                int temp=A[i];                A[i]=A[largest];                A[largest]=temp;                max_heap(A,largest,heapsize);}}//建堆,从len/2以后的位置节点均为子节点,而且必须从后往前建堆即从//len/2--->1void build_max_heap(int A[],int len){        int i=0;        for(i=len/2;i>=1;i--){        max_heap(A,i,len);}}//每次取最大的放在最后,剩下的调整位置成为一个新的堆void heap_sort(int A[],int heapsize){        while(heapsize>=1){        int temp=0;        temp=A[heapsize];        A[heapsize]=A[1];        A[1]=temp;        heapsize--;        max_heap(A,1,heapsize);}}int main(){        int len=10;        int A[]={0,2,3,6,2,16,9,10,14,8,7};        build_max_heap(A,10);        heap_sort(A,heapsize);        int i=0;        for(i=1;i<=len;i++)                printf("%d ",A[i]);        printf("\n");        return 0;}

下面给出最大优先队列实现代码:

#include<stdio.h>#include<malloc.h>typedef struct Heap{  //定义一个堆数据结构,主要为了封装heapsize        int data[20];        int heapsize;}heap;int parent(int i){        return i/2;}int left(int i){        return 2*i;}int right(int i){        return 2*i+1;}//保持堆的性质void max_heap(heap *A,int i){        int l=left(i);        int r=right(i);        int largest=i;        if(l<=A->heapsize&&A->data[l]>A->data[largest]){                largest=l;        }        if(r<=A->heapsize&&A->data[r]>A->data[largest]){                largest=r;        }        if(i!=largest){                int temp;                temp=A->data[i];                A->data[i]=A->data[largest];                A->data[largest]=temp;                max_heap(A,largest);        }}void build_max_heap(heap* A){  //建堆        int i=0;        for(i=(A->heapsize)/2;i>=1;i--){                max_heap(A,i);        }}int heap_maxmun(heap *A){         //return the max value        return A->data[1];}int heap_extract_max(heap *A){          //return and remove max value        int temp=0;        temp=A->data[A->heapsize];        A->data[A->heapsize]=A->data[1]; A->data[1]=temp;        max_heap(A,1);        A->heapsize--;        return A->data[A->heapsize+1];}void heap_incresment_key(heap *A,int i,int key){        if(A->data[i]>key)                return;        A->data[i]=key;        while (i>1&&A->data[parent(i)]<A->data[i])                {                        int temp=A->data[i];                        A->data[i]=A->data[parent(i)];                        A->data[parent(i)]=temp;                        i=parent(i);                }}void heap_max_heap_insert(heap *A,int key){        A->heapsize++;        A->data[A->heapsize]=0;        heap_incresment_key(A,A->heapsize,key);}int main(){        heap* A=(heap*)malloc(sizeof(heap));        int i=0;        for(i=0;i<=10;i++){        A->data[i]=i;        }//      A.data={0,1,2,3,4,5,6,7,8,9,10};        A->heapsize=10;        build_max_heap(A);        for(i=1;i<=A->heapsize;i++){                printf("%d ",A->data[i]);        }        printf("\n"); printf("%d",heap_extract_max(A));        printf("\n");        heap_max_heap_insert(A,10);        heap_incresment_key(A,3,11);        for(i=1;i<=A->heapsize;i++)                printf("%d ",A->data[i]);        printf("\n");}
1 0