堆的基础知识

堆的基本性质

也可以说是一个完全二叉树,就是除了最底层的,其它层是满的,既然我们可以用完全二叉树来表示一个堆,那么我们这里就采用数组结构的二叉树来阐述堆的性质。

假设在这里我们用数组A表示堆,A[i]表示堆里面的第i个元素,于是我们通过二叉树的性质可知:

  • PARENT(i) = i/2
  • LEFTCHILD(i) = 2*i
  • RIGHTCHILD(i) = 2*i+1

就如下图表现所示:

小优化:

我们知道在计算机里面做乘法和除法是特别慢的。但是某些时候,我们就可以采用左移和右移来代替乘以2和除以2的操作,比如1<<2,那么就是2,4>>1,那么结果就是2,我们知道左移和右移的操作是非常迅速的。所以我们在计算父节点坐标和子节点坐标的时候可以采用这种方法来实现:


#define PARENT(i) ((i)>>2)

#define LEFTCHILD(i) ((i)<<2)

#define RIGHTCHILD(i) (((i)<<2)+1)

堆的分类

在堆里面,我们可以大致将堆分为三类

  • 最小堆
  • 最大堆

最小堆

只要在二叉树结构里面,对于除了根节点意外的任何节点i都满足:

A[PARENT[i]]<A[i]

那么就称具有这种性质的堆为最小堆

最大堆

与最小堆类似,只要在二叉树结构里面,对于除了根节点意外的任何节点i都满足:

A[PARENT[i]]>A[i]

那么就称具有这种性质的堆为最大堆

对于即即使最小堆也不是最大堆的堆来说,这种对我们就称之为

维护堆的性质

假如我们改变最大堆里面的一个元素的大小,那么整个最大堆的性质将会被破坏,这里我们需要找到一种在改变了最大堆或者是最小堆的元素的情况下,进行一定变换就可以保持堆原有性质的方法!

因为最大堆和最小堆基本类似,于是我们在这里选出最大堆进行讲解,我们假设维护最大堆性质的函数为MAX-HEAPIFY(A,i),这里输入需要维护的堆A和改变的元素位置i。在堆A进行维护之前,必须保证i节点的左子树LEFT(i)和右子树RIGHT(i)有最大堆的性质,这一点很重要

下面我们用伪代码实现MAX-HEAPIFY(A,i)

MAX-HEAPIFY(A,i)
if i >= A.heapsize
    return
leftChild = LEFTCHILD(i)
rightChild = RIGHTCHILD(i);
maxPos = i
if A[leftChild] > A[i]:
    maxPos = leftChild;
if A[rightChild] > A[maxPos]:
    maxPos = rightChild;
if(maxPos == i)
    return;
exchange(A,maxPos,i)
MAX-HEAPIFY(A,maxPos)

在这里,我们采用将元素沉降的方法,将较小的元素向下沉降,较大的元素向上移动,假设我们这里有这样一个例子:

假设以i为根节点一棵子树,现在我们要对其从根节点开始进行最大堆的性质维护,那么我们需要多大的时间花费呢

T(n)≤T(n2/3)+O(1)

证明:

假设我们有一棵完全二叉树T,这棵二叉树有n个节点,高度为h+1,那么在将根节点去掉以后左子树剩余节点数最多为:(2h+1?2)/2+2h=2?2h?1(T的最底层元素个数为T为满二叉树时最底层元素个数的一半),,在去掉根节点以后,剩下的总结点个数为2h+1+2h?1=3?2h?1 ,那么在在去掉根节点以后,左子树的节点数量与及剩下总节点个数相比为2?2h?13?2h?1,于是limh→∞2?2h?13?2h?1=23

所以按照主定理,我们知道维护堆性质的时间代价为O(logn)

时间: 2024-10-10 03:21:51

堆的基础知识的相关文章

数组、栈、堆(java基础知识五)

1.数组概述.定义格式 * A:数组概念 数组是存储同一种数据类型多个元素的集合.也可以看成是一个容器. 数组既可以存储基本数据类型,也可以存储引用数据类型. * B:数组定义格式 格式1:数据类型[] 数组名;----int[] arr; 格式2:数据类型 数组名[];----int arr[]; * C:数组是存储多个变量(元素)的东西(容器),这多个变量的数据类型要一致, 2.数组初始化.动态初始化 * A:什么是数组的初始化 Java中的数组必须先初始化,然后才能使用. 所谓初始化:就是

【Python数据挖掘课程】六.Numpy、Pandas和Matplotlib包基础知识

前面几篇文章采用的案例的方法进行介绍的,这篇文章主要介绍Python常用的扩展包,同时结合数据挖掘相关知识介绍该包具体的用法,主要介绍Numpy.Pandas和Matplotlib三个包.目录:        一.Python常用扩展包        二.Numpy科学计算包        三.Pandas数据分析包        四.Matplotlib绘图包 前文推荐:       [Python数据挖掘课程]一.安装Python及爬虫入门介绍       [Python数据挖掘课程]二.K

多线程编程基础知识

多线程编程基础知识 http://www.cnblogs.com/cy163/archive/2006/11/02/547428.html 当前流行的Windows操作系统能同时运行几个程序(独立运行的程序又称之为进程),对于同一个程序,它又可以分成若干个独立的执行流,我们称之为线程,线程提供了多任务处理的能力.用进程和线程的观点来研究软件是当今普遍采用的方法,进程和线程的概念的出现,对提高软件的并行性有着重要的意义.现在的大型应用软件无一不是多线程多任务处理,单线程的软件是不可想象的.因此掌握

C#基础知识篇(五)-----------C#笔记

一.值类型和引用类型 1>值类型和引用类型将我们学过的数据类型划分成了两部分. 划分的依据是不同类型的数据在内存中(堆栈)存储的结构不同. 2>值类型:所有的数值类型:long int short byte ulong uint ushort sbyte decimal duoble float char bool 枚举 结构 3>引用类型:string,arry(数组),类(class) 4>不管是值类型还是引用类型赋值都是将数据copy一份将副本赋给变量,不同的是值类型拷贝的是

C#基础知识篇(四)-----------C#笔记

一.类 1. 什么叫做类? 类是具有相同特征的一类事物统称.所以类是一种抽象,即不是一个实体(我们把类看做模板). 2. 什么叫做对象? 对象是根据类的模板创造出来的一个实体,它具有类里所有的特征,一个也多不得,一个也少不得.少了就不叫这个类的成员了,多了也不是!假如张三有变身这个功能,那么张三就不属于人. 记住对象是根据模板创建的,模板有什么它就有什么,不会多也不会少! 3. 什么叫做字段(或者是成员变量)? 我们把定义在方法的外面,类的里面(即:类中)的变量称之为字段或者说是成员变量. 4.

线程基础知识系列(三)线程的同步

本文是系列的第三篇,前面2篇,主要是针对单个线程如何管理,启动等,没有过多涉及多个线程是如何协同工作的. 线程基础知识系列(二)线程的管理 :线程的状态,控制,休眠,Interrupt,yield等 线程基础知识系列(一)线程的创建和启动  :线程的创建和启动,join(),daemon线程,Callable任务. 本文的主要内容 何谓线程安全? 何谓共享可变变量? 认识synchronized关键字 认识Lock synchronized vs Lock 1.何谓线程安全 多线程是把双刃剑,带

Java中String的基础知识

Java中String的基础知识 ==与equal的区别 基本数据类型,指的是java中的八种基本数据结构(byte,short,char,int,long,float,double,boolean),一般的比较是使用的 ==,比较的是他们的值. 复合数据类型(类) ==比较的是两个对象的引用,可以理解为在内存中的地址,除非是同一个new出来的对象,他们的 ==为true,否则,都为false. equal是object中的方法.object中的实现如下,内部还是使用==实现,也就是说,如果一个

C#基础知识之一

C#基础知识 1.类型:13种预定义简单类型,2种预定义非简单类型object.string ,6种用户自定义类型class.struct.array.enum.delegate.interface. 2.对于一个引用类型,其实例的数据成员存放在堆里,无论实例的成员是值类型还是引用类型. 3.本地变量在未赋值之前不能使用. 4.数据成员:存储与类或类实例相关的数据.函数成员:执行代码. 5.字段是数据成员,方法是函数成员. 6.在类型的外部不能声明全局变量(也就是变量或字段),必须在类型声明内部

C#学习笔记(基础知识回顾)之值类型与引用类型转换(装箱和拆箱)

一:值类型和引用类型的含义参考前一篇文章 C#学习笔记(基础知识回顾)之值类型和引用类型 1.1,C#数据类型分为在栈上分配内存的值类型和在托管堆上分配内存的引用类型.如果int只不过是栈上的一个4字节的值,该如何在它上面调用方法? 二:值类型转换为引用类型--装箱 2.1CLR对值类型进行装箱时:新分配托管堆内存,将值类型的实例字段拷贝到新分配的内存中,返回托管堆中新分配对象的地址.这个地址就是一个指向对象的引用. int i = 10; Object obj = i; 三:将引用类型转换为值