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当前的元素数目

下面给出其主要的四个操作(以大顶堆为例):

2.1 Heapify(A,n,t)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void Heapify(int A[], int n, int t)
 
{
 
  int left = LEFT(t);
 
  int right = RIGHT(t);
 
  int max = t;
 
  if(left <= n)     max = A[left] > A[max] ? left : max;
 
  if(right <= n)     max = A[right] > A[max] ? right : max;
 
  if(max != A[t])
 
  {
 
    swap(A, max, t);
 
    Heapify(A, n, max);
 
  }
 
}

2.2  BuildHeap(A,n)

该操作主要是将数组A转化成一个大顶堆。思想是,先找到堆的最后一个非叶子节点(即为第n/2个节点),然后从该节点开始,从后往前逐个调整每个子树,使之称为堆,最终整个数组便是一个堆。

1
2
3
4
5
6
7
8
9
10
11
void BuildHeap(int A[], int n)
 
{
 
  int i;
 
  for(i = n/2; i<=n; i++)
 
  Heapify(A, n, i);
 
}

2.3 GetMaximum(A,n)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
void GetMaximum(int A[], int n)
 
{
 
  int max = A[1];
 
  A[1] = A[n];
 
  n--;
 
  Heapify(A, n, 1);
 
  return max;
 
}

2.4  Insert(A, n, t)

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
void Insert(int A[], int n, int t)
 
{
 
  n++;
 
  A[n] = t;
 
  int p = n;
 
  while(p >1 && A[PARENT(p)] < t)
 
  {
 
    A[p] = A[PARENT(p)];
 
    p = PARENT(p);
 
  }
 
  A[p] = t;
 
  return max;
 
}

3.  堆的应用

3.1  堆排序

堆的最常见应用是堆排序,时间复杂度为O(N lg N)。如果是从小到大排序,用大顶堆;从大到小排序,用小顶堆。

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

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

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

4. 总结

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

5. 参考资料

(1)经典算法教程《算法导论》

———————————————————————————————

更多关于数据结构和算法的介绍,请查看:数据结构与算法汇总

———————————————————————————————-

原创文章,转载请注明: 转载自董的博客

本文链接地址: http://dongxicheng.org/structure/heap/

 
 

数据结构之堆Heap的更多相关文章

  1. python数据结构之堆(heap)

    本篇学习内容为堆的性质.python实现插入与删除操作.堆复杂度表.python内置方法生成堆. 区分堆(heap)与栈(stack):堆与二叉树有关,像一堆金字塔型泥沙:而栈像一个直立垃圾桶,一列下 ...

  2. 算法与数据结构基础 - 堆(Heap)和优先级队列(Priority queue)

    堆基础 堆(Heap)是具有这样性质的数据结构:1/完全二叉树 2/所有节点的值大于等于(或小于等于)子节点的值: 图片来源:这里 堆可以用数组存储,插入.删除会触发节点shift_down.shif ...

  3. 数据结构 - 堆(Heap)

    数据结构 - 堆(Heap) 1.堆的定义 堆的形式满足完全二叉树的定义: 若 i < ceil(n/2) ,则节点i为分支节点,否则为叶子节点 叶子节点只可能在最大的两层出现,而最大层次上的叶 ...

  4. 算法手记 之 数据结构(堆)(POJ 2051)

    一篇读书笔记 书籍简评:<ACM/ICPC 算法训练教程>这本书是余立功主编的,代码来自南京理工大学ACM集训队代码库,所以小编看过之后发现确实很实用,适合集训的时候刷题啊~~,当时是听了 ...

  5. 堆heap和栈Stack(百科)

    堆heap和栈Stack 在计算机领域,堆栈是一个不容忽视的概念,堆栈是两种数据结构.堆栈都是一种数据项按序排列的数据结构,只能在一端(称为栈顶(top))对数据项进行插入和删除.在单片机应用中,堆栈 ...

  6. iOS中的堆(heap)和栈(stack)的理解

    操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:“text segment “,“stack segment ”,“heap segme ...

  7. Java中堆(heap)和栈(stack)的区别

    简单的说: Java把内存划分成两种:一种是栈内存,一种是堆内存. 在函数中定义的一些基本类型的变量和对象的引用变量都在函数的栈内存中分配. 当在一段代码块定义一个变量时,Java就在栈中为这个变量分 ...

  8. 纸上谈兵: 堆 (heap)

    纸上谈兵: 堆 (heap)   作者:Vamei 出处:http://www.cnblogs.com/vamei 欢迎转载,也请保留这段声明.谢谢! 堆(heap)又被为优先队列(priority ...

  9. iOS数据存储类型 及 堆(heap)和栈(stack)

    iOS数据存储类型 及 堆(heap)和栈(stack) 一般认为在c中分为这几个存储区: 1栈 --  由编译器自动分配释放. 2堆 --  一般由程序员分配释放,若程序员不释放,程序结束时可能由O ...

随机推荐

  1. UVA732【DFS+栈】

    题目:已知两个单词,利用一个栈,将第一个单词变成第二个单词,求出所有可能的操作序列. #include <stdio.h> #include<iostream> #includ ...

  2. 类相关的BIF

    1.>>> issubclass(C,A)#判断c是A的子类,返回真假 2.>>> isinstance(b1,B) #判断c1是B类的实例化对象,返回真假 3.& ...

  3. 【转】python3 urllib.request 网络请求操作

    python3 urllib.request 网络请求操作 基本的网络请求示例 ''' Created on 2014年4月22日 @author: dev.keke@gmail.com ''' im ...

  4. 解析spring中的BeanFactory

    我们常把spring看作一个bean工厂或者ioc容器,它帮助我们负责对象的创建管理,以及对象间依赖关系的建立,还有其他的功能. 关于工厂的实现,一般来说与我们接触最多的就是BeanFactory和A ...

  5. 原生js代码挑战之动态添加双色球

    var ballArr = []; //存放已有的红球,用来排除重复和排序window.onload = function(){ var btn = document.createElement(&q ...

  6. 洞见世界(1): 拉勾网大数据告诉你, 会计最高月薪达33k!

    前言: 小李是个很有上进心的女孩, 老板让她了解下会计这个行业的薪资情况, 她不清楚怎么去做, 所以找了笔者, 当当当, 然后这一份薪资报告就出来了^_^.(小李为虚拟人物) by  璀璨者张健, 专 ...

  7. [LeetCode] Can Place Flowers 可以放置花

    Suppose you have a long flowerbed in which some of the plots are planted and some are not. However, ...

  8. [LeetCode] Diameter of Binary Tree 二叉树的直径

    Given a binary tree, you need to compute the length of the diameter of the tree. The diameter of a b ...

  9. Python 内置方法

    1. abs() 取绝对值函数 #!/usr/bin/env python # _*_ coding: UTF-8 _*_ # Author:taoke i = 100 print(abs(i)) i ...

  10. 安卓开发JAVA基础之初识JAVA

    JAVA的一大特点------不依赖平台 JAVA在平台之上提供了一个JAVA运行环境(Java  Runtime Environment, JRE),该环境由Java虚拟机(Java  Virtua ...