数据结构之“堆”

转载自http://www.cnblogs.com/Jason-Damon/archive/2012/04/18/2454649.html


1.堆

    堆数据结构是一种数组对象,它可以被视为一科完全二叉树结构。它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆)。它常用于管理算法执行过程中的信息,应用场景包括堆排序优先队列等。

2. 堆的基本操作

    堆是一棵完全二叉树,高度为O(lg n),其基本操作至多与树的高度成正比。在介绍堆的基本操作之前,先介绍几个基本术语:

 

    A:用于表示堆的数组,下标从1开始,一直到n

 

  PARENT(t):节点t的父节点,即floor(t/2)

 

  RIGHT(t):节点t的左孩子节点,即:2*t

 

    LEFT(t):节点t的右孩子节点,即:2*t+1

 

    HEAP_SIZE(A):堆A当前的元素数目

 3.保持堆的性质 Heapify(A,n,t)

 

     该操作主要用于维持堆的基本性质。假定以RIGHT(t)和LEFT(t)为根的子树都已经是堆,然后调整以t为根的子树,使之成为堆。

 

    

复制代码
void Heapify(int A[],int i)
{
    int l=LEFT(i);
    int r=RIGHT(i);
    int largest;
    if(l<=HEAP_SIZE(A)) largest=A[l]>A[i]?l:i;
        if(r<=HEAP_SIZE(A)) largest=A[r]>A[largest]?r:largest;  //从i,2*i,2*i+1中找出最大的一个
        if(largest!=i)    //i不是最大的
    {
        swap(A[i],A[largest]);
        Heapify(A,largest);  //交换后,子树有可能违反最大堆性质
    }
}
复制代码

 


4.建堆 BuildHeap(A,n)

    操作主要是将数组A转化成一个大顶堆。思想是,先找到堆的最后一个非叶子节点(即为第n/2个节点),然后从该节点开始,从后往前逐个调整每个子树,使之称为堆,最终整个数组便是一个堆。子数组A[(n/2)+1..n]中的元素都是树中的叶子,因此都可以看作是只含有一个元素的堆。具体的过程我觉得看《算法导论》里面的图的话理解应该很简单,我找不到那图。

void BuildHeap(int A[],)  
 {    
            int i;
            for(i = HEAP_SIZE(A)/2; i>=1; i--)    
               Heapify(A, i); 
  } 

 

5.堆排序算法   

     先用BuildHeapo将数组A[1..n]构造成一个最大堆。因为数组中最大元素在根A[1],则可以通过把它与A[n]交换来达到最终正确的位置。

 

复制代码
void HeapSort(int A[])
{
    BuildHeap(A);
    for(i=HEAP_SIZE(A),i>1; i--)
    {
        swap(A[1],A[i]);
        HEAP_SIZE(A)=HEAP_SIZE(A)-1;
        Heapify(A,1);  //交换后新的根元素可能委培了最大堆的性质
    }
}
复制代码

 

6.优先队列  priority queue

    优先队列是一种用来维护由一组元素构成的集合S的数据机构。相信大家对它都有所了解。虽然说c++里面有了priority_queue,但我们还是要了解它的一些基本构成及实现的代码。

GETMAX:

该操作主要是获取堆中最大的元素,同时保持堆的基本性质。堆的最大元素即为第一个元素,将其保存下来,同时将最后一个元素放到A[1]位置,之后从上往下调整A,使之成为一个堆。

复制代码
void GetMaximum(int A[])   {
     int max = A[1];
     A[1] = A[n];
     HEAP_SIZE--;
     Heapify(A, n, 1);
     return max;
   } 
复制代码

INSERT:

向堆中添加一个元素t,同时保持堆的性质。算法思想是,将t放到A的最后,然后从该元素开始,自下向上调整,直至A成为一个大顶堆。

复制代码
void Insert(int A[], int i)   {  //i为插入的值
    int n=++HEAP_SIZE(A);     
    A[n] = -99999;//小无穷
     int p = n;
     while(p >1 && A[PARENT(p)] < i)  {
       A[p] = A[PARENT(p)];
       p = PARENT(p);
      }
      A[p]=i;
}
复制代码

    总结。

     堆的最常见应用是堆排序,时间复杂度为O(N lg N)。如果是从小到大排序,用小顶堆;从大到小排序,用大顶堆。虽然堆排序是一个很漂亮的算法,但实际中,快排的一个好的实现往往优于堆排序。尽管这样,对数据结构还是有着很大的用处,比如说优先队列。

    例子:  在O(n lg k)时间内,将k个排序表合并成一个排序表,n为所有有序表中元素个数。

【解析】取前100 万个整数,构造成了一棵数组方式存储的具有小顶堆,然后接着依次取下一个整数,如果它大于最小元素亦即堆顶元素,则将其赋予堆顶元素,然后用Heapify调整整个堆,如此下去,则最后留在堆中的100万个整数即为所求 100万个数字。该方法可大大节约内存。

   例子:一个文件中包含了1亿个随机整数,如何快速的找到最大(小)的100万个数字?(时间复杂度:O(n lg k))

堆是一种非常基础但很实用的数据结构,很多复杂算法或者数据结构的基础就是堆,因而,了解和掌握堆这种数据结构显得尤为重要。

 


购物商城项目采用PHP+mysql有以及html+css jq以及layer.js datatables bootstorap等插件等开发,采用了MVC模式,建立一个完善的电商系统,通过不同用户的不同需求,进行相应的调配和处理,提高对购买用户进行配置….zip项目工程资源经过严格测试可直接运行成功且功能正常的情况才上传,可轻松复刻,拿到资料包后可轻松复现出一样的项目,本人系统开发经验充足(全领域),有任何使用问题欢迎随时与我联系,我会及时为您解惑,提供帮助。 【资源内容】:包含完整源码+工程文件+说明(如有)等。答辩评审平均分达到96分,放心下载使用!可轻松复现,设计报告也可借鉴此项目,该资源内项目代码都经过测试运行成功,功能ok的情况下才上传的。 【提供帮助】:有任何使用问题欢迎随时与我联系,我会及时解答解惑,提供帮助 【附带帮助】:若还需要相关开发工具、学习资料等,我会提供帮助,提供资料,鼓励学习进步 【项目价值】:可用在相关项目设计中,皆可应用在项目、毕业设计、课程设计、期末/期中/大作业、工程实训、大创等学科竞赛比赛、初期项目立项、学习/练手等方面,可借鉴此优质项目实现复刻,设计报告也可借鉴此项目,也可基于此项目来扩展开发出更多功能 下载后请首先打开README文件(如有),项目工程可直接复现复刻,如果基础还行,也可在此程序基础上进行修改,以实现其它功能。供开源学习/技术交流/学习参考,勿用于商业用途。质量优质,放心下载使用。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值