数据结构之堆

1。概念:堆是一种特殊的二叉树,具备以下两种性质
1)每个节点的值都大于(或者都小于,称为最小堆)其子节点的值
2)树是完全平衡的,并且最后一层的树叶都在最左边
这样就定义了一个最大堆。

2。堆可以用一个数组表示,有如下性质:
heap[i]>=heap[2*i+1]  其中0<=i<=(n-1)/2
heap[i]>=heap[2*i+2]  其中0<=i<=(n-2)/2

3。用数组实现堆,
1)插入操作
自顶向下,伪代码:

  heapEnqueue(el)
      将el放在堆尾
      while el不在根节点并且el>parent(el)
          交换el及其父节点

自底向上,伪代码:

 FloydAlgrithm(data[])
     for i=最后一个非叶节点的下标,i>=0;i--
      调用moveDown(data,i,n-1)恢复以data[i]为根的树的堆性质


  
2)moveDown的方法实现,此方法是堆排序的关键,也是删除操作的关键。删除操作,将根节点删除,并把最末的树叶换到根节点,通过moveDown方法找到正确的位置,恢复堆性质。

4。堆的一个实现:

// heap.java
// demonstrates heaps
// to run this program: C>java HeapApp
import java.io.*;
////////////////////////////////////////////////////////////////
class Node
{
private int iData;             // data item (key)
// -------------------------------------------------------------
public Node(int key)           // constructor
{ iData = key; }
// -------------------------------------------------------------
public int getKey()
{ return iData; }
// -------------------------------------------------------------
public void setKey(int id)
{ iData = id; }
// -------------------------------------------------------------
}  // end class Node
////////////////////////////////////////////////////////////////
class Heap
{
private Node[] heapArray;
private int maxSize;           // size of array
private int currentSize;       // number of nodes in array
// -------------------------------------------------------------
public Heap(int mx)            // constructor
{
maxSize = mx;
currentSize = 0;
heapArray = new Node[maxSize];  // create array
}
// -------------------------------------------------------------
public boolean isEmpty()
{ return currentSize==0; }
// -------------------------------------------------------------
public boolean insert(int key)
{
if(currentSize==maxSize)
return false;
Node newNode = new Node(key);
heapArray[currentSize] = newNode;
trickleUp(currentSize++);
return true;
}  // end insert()
// -------------------------------------------------------------
public void trickleUp(int index)
{
int parent = (index-1) / 2;
Node bottom = heapArray[index];

while( index > 0 &&
heapArray[parent].getKey() < bottom.getKey() )
{
heapArray[index] = heapArray[parent];  // move it down
index = parent;
parent = (parent-1) / 2;
}  // end while
heapArray[index] = bottom;
}  // end trickleUp()
// -------------------------------------------------------------
public Node remove()           // delete item with max key
{                           // (assumes non-empty list)
Node root = heapArray[0];
heapArray[0] = heapArray[--currentSize];
trickleDown(0);
return root;
}  // end remove()
// -------------------------------------------------------------
public void trickleDown(int index)
{
int largerChild;
Node top = heapArray[index];       // save root
while(index < currentSize/2)       // while node has at
{                               //    least one child,
int leftChild = 2*index+1;
int rightChild = leftChild+1;
// find larger child
if(rightChild < currentSize &&  // (rightChild exists?)
heapArray[leftChild].getKey() <
heapArray[rightChild].getKey())
largerChild = rightChild;
else
largerChild = leftChild;
// top >= largerChild?
if( top.getKey() >= heapArray[largerChild].getKey() )
break;
// shift child up
heapArray[index] = heapArray[largerChild];
index = largerChild;            // go down
}  // end while
heapArray[index] = top;            // root to index
}  // end trickleDown()
// -------------------------------------------------------------
public boolean change(int index, int newValue)
{
if(index<0 || index>=currentSize)
return false;
int oldValue = heapArray[index].getKey(); // remember old
heapArray[index].setKey(newValue);  // change to new

if(oldValue < newValue)             // if raised,
trickleUp(index);                // trickle it up
else                                // if lowered,
trickleDown(index);              // trickle it down
return true;
}  // end change()
// -------------------------------------------------------------
public void displayHeap()
{
System.out.print("heapArray: ");    // array format
for(int m=0; m<currentSize; m++)
if(heapArray[m] != null)
System.out.print( heapArray[m].getKey() + " ");
else
System.out.print( "-- ");
System.out.println();
// heap format
int nBlanks = 32;
int itemsPerRow = 1;
int column = 0;
int j = 0;                          // current item
String dots = "...............................";
System.out.println(dots+dots);      // dotted top line

while(currentSize > 0)              // for each heap item
{
if(column == 0)                  // first item in row?
for(int k=0; k<nBlanks; k++)  // preceding blanks
System.out.print(' ');
// display item
System.out.print(heapArray[j].getKey());

if(++j == currentSize)           // done?
break;

if(++column==itemsPerRow)        // end of row?
{
nBlanks /= 2;                 // half the blanks
itemsPerRow *= 2;             // twice the items
column = 0;                   // start over on
System.out.println();         //    new row
}
else                             // next item on row
for(int k=0; k<nBlanks*2-2; k++)
System.out.print(' ');     // interim blanks
}  // end for
System.out.println("/n"+dots+dots); // dotted bottom line
}  // end displayHeap()
// -------------------------------------------------------------
}  // end class Heap
////////////////////////////////////////////////////////////////
class HeapApp
{
public static void main(String[] args) throws IOException
{
int value, value2;
Heap theHeap = new Heap(31);  // make a Heap; max size 31
boolean success;

theHeap.insert(70);           // insert 10 items
theHeap.insert(40);
theHeap.insert(50);
theHeap.insert(20);
theHeap.insert(60);
theHeap.insert(100);
theHeap.insert(80);
theHeap.insert(30);
theHeap.insert(10);
theHeap.insert(90);

while(true)                   // until [Ctrl]-[C]
{
System.out.print("Enter first letter of ");
System.out.print("show, insert, remove, change: ");
int choice = getChar();
switch(choice)
{
case 's':                        // show
theHeap.displayHeap();
break;
case 'i':                        // insert
System.out.print("Enter value to insert: ");
value = getInt();
success = theHeap.insert(value);
if( !success )
System.out.println("Can't insert; heap full");
break;
case 'r':                        // remove
if( !theHeap.isEmpty() )
theHeap.remove();
else
System.out.println("Can't remove; heap empty");
break;
case 'c':                        // change
System.out.print("Enter current index of item: ");
value = getInt();
System.out.print("Enter new key: ");
value2 = getInt();
success = theHeap.change(value, value2);
if( !success )
System.out.println("Invalid index");
break;
default:
System.out.println("Invalid entry/n");
}  // end switch
}  // end while
}  // end main()
//-------------------------------------------------------------
public static String getString() throws IOException
{
InputStreamReader isr = new InputStreamReader(System.in);
BufferedReader br = new BufferedReader(isr);
String s = br.readLine();
return s;
}
//-------------------------------------------------------------
public static char getChar() throws IOException
{
String s = getString();
return s.charAt(0);
}
//-------------------------------------------------------------
public static int getInt() throws IOException
{
String s = getString();
return Integer.parseInt(s);
}
//-------------------------------------------------------------
}  // end class HeapApp
////////////////////////////////////////////////////////////////
文章转自庄周梦蝶  ,原文发布时间5.17
时间: 2024-10-11 17:40:23

数据结构之堆的相关文章

数据结构最小堆的问题,求解

问题描述 数据结构最小堆的问题,求解 对于键值序列{38735215644048552612},用筛选法建最小值堆,共交换元素多少次? 解决方案 http://wenku.baidu.com/link?url=BQHXTOB98jZG3atI_EqajsCSh3gBVI-jU4LcjPzdqozBhY267ODYAnADWJoZ6Yj0kFS5tjb_rQYLxoW6SsteWWX4tQTNS_pNHffVO-vDQxO看problem 3-26次 解决方案二: [数据结构]递归求解迷宫问题

数据结构之堆和栈

 内存分配策略     按照编译原理的观点,程序运行时的内存分配有三种策略,分别是静态的,栈式的,和堆式的.  静态存储分配是指在编译时就能确定每个数据目标在运行时刻的存储空间需求,因而在编译时就可以给他们分配固定的内存空间.这种分配策略要求程序代码中不允许有可变数据结构(比如可变数组)的存在,也不允许有嵌套或者递归的结构出现,因为它们都会导致编译程序无法计算准确的存储空间需求.  栈式存储分配也可称为动态存储分配,是由一个类似于堆栈的运行栈来实现的.和静态存储分配相反,在栈式存储方案中,程序对

数据结构之堆详解_C 语言

1. 概述 堆(也叫优先队列),是一棵完全二叉树,它的特点是父节点的值大于(小于)两个子节点的值(分别称为大顶堆和小顶堆).它常用于管理算法执行过程中的信息,应用场景包括堆排序,优先队列等. 2. 堆的基本操作 堆是一棵完全二叉树,高度为O(lg n),其基本操作至多与树的高度成正比.在介绍堆的基本操作之前,先介绍几个基本术语: A:用于表示堆的数组,下标从1开始,一直到n PARENT(t):节点t的父节点,即floor(t/2) RIGHT(t):节点t的左孩子节点,即:2*t LEFT(t

PHP SPL标准库之数据结构堆(SplHeap)简单使用实例_php实例

堆(Heap)就是为了实现优先队列而设计的一种数据结构,它是通过构造二叉堆(二叉树的一种)实现.根节点最大的堆叫做最大堆或大根堆,根节点最小的堆叫做最小堆或小根堆.二叉堆还常用于排序(堆排序). 如下:最小堆(任意节点的优先级不小于它的子节点) 看看PHP SplHeap的实现: 显然它是一个抽象类,最大堆(SplMaxHeap)和最小堆(SplMinHeap)就是继承它实现的.最大堆和最小堆并没有额外的方法 SplHeap的简单使用如下: class MySimpleHeap extends

语言堆栈入门——堆和栈的区别

原文:http://student.csdn.net/link.php?url=http://www.top-e.org%2Fjiaoshi%2Fhtml%2F427.html 格式和部分内容稍作修改. 在计算机领域,堆栈是一个不容忽视的概念,我们编写的C语言程序基本上都要用到.但对于很多的初学着来说,堆栈是一个很模糊的概念.堆栈:一种数据结构.一个在程序运行时用于存放的地方,这可能是很多初学者的认识,因为我曾经就是这么想的和汇编语言中的堆栈一词混为一谈.我身边的一些编程的朋友以及在网上看帖遇到

【转载】iOS堆和栈的理解

操作系统iOS 中应用程序使用的计算机内存不是统一分配空间,运行代码使用的空间在三个不同的内存区域,分成三个段:"text segment ","stack segment ","heap segment ". 段"text segment "是应用程序运行时应用程序代码存在的内存段.每一个指令,每一个单个函数.过程.方法和执行代码都存在这个内存段中直到应用程序退出.一般情况下,你不会真的不得不知道这个段的任何事情. 当应用开

详解堆的javascript实现方法_javascript技巧

堆的定义 最大(最小)堆是一棵每一个节点的键值都不小于(大于)其孩子(如果存在)的键值的树.大顶堆是一棵完全二叉树,同时也是一棵最大树.小顶堆是一棵完全完全二叉树,同时也是一棵最小树. 另外,记住这两个概念,对写代码太重要了:       1.父节点和子节点的关系:看定义       2.完全二叉树:参考[2] 基本操作       1.Build(构建堆)       2.Insert(插入)       3.Delete(删除:最小或者最大的那个) 代码实现 首先,写代码前有两个非常重要的点

可视化的数据结构和算法

导读:作者陈皓之前写过关于可视化排序的一篇文章,现在他又给大家罗列出可视化的数据结构和算法来供大家学习参考.文中分别从基础.索引.排序.动态编程等方面进行描述. 文章内容如下: 还记得之前发布过的那个关于可视化排序的文章吗?在网上又看到了一个旧金山大学David Galles做的各种可视化的数据结构和基本算法的主页,网址在这里,大家可以看看.我把这个页面的目录列在下面并翻译了一下,大家可以直接点击了. 不知道国内的教育有没有相关的教学课件,至少在我大学的时候是没有的. 基础 Stack栈: 数组

二叉树的性质和应用

二叉树的性质 二叉树是图的一种特殊情形. 二叉树与有序树:在只有一个孩子结点的情况下,二叉树有左右之分.有序树无左右之分.   非空二叉树中,共有n个结点,度为0的结点有n0个,度为1的结点有n1个,度为2的结点有n2个,则n0=n2+1; 推导:n=n0+n1+n2;            n-1=n1+2*n2;  联立得解.(最爱考这个了...)   非空二叉树第i层上至多有2^(i-1)个结点://pow(2,i-1) 高为h的二叉树最多有2^h-1个结点://pow(2,h)-1