堆的数组实现



用数组来实现堆比链式实现简单,这是因为:

1)在插入操作中,链式实现需要一个getInsertNode方法去找插入在哪个结点之下,而在数组中,插入结点的位置下标是依次递增的,(完全二叉树)

插入操作的向上调整也可以直接根据下标来找父节点(思维和链式一样)

2)在删除堆顶的操作中,链式实现把lastNode的值赋给堆顶后,还要去找倒数第二个结点来更新lastNode,而在数组里就不需要,直接根据下标就知道哪个是倒数第二个结点,而且也不需要记录lastNode。

删除操作的自上往下调整,左右子节点也可以通过下标来定,这个思路和链式一样,也是用递归,只是改为了下标来移动


经过上面的比较和分析,数组怎么去实现已经很清楚了,下面简要介绍:



1,实例变量,构造方法,数组扩展

private Comparable[] contents;
private int count; //count不仅表示大小,还表示下一个存储位置,注意堆是一棵完全二叉树

public ArrayHeap()
{
contents
= new Comparable[10];
count
= 0;
}

public ArrayHeap(Comparable ele)
{
contents
= new Comparable[10];
contents[
0] = ele;
count
= 1;
}

public void expand()
{
Comparable[] larger
= new Comparable[contents.length*3];
for(int i =0;i < size();i++)
larger[i]
= contents[i];
contents
= larger;
}



2,插入操作

public void addElement(Comparable element) {
// TODO Auto-generated method stub
if(size() == contents.length)
expand();
contents[count]
= element; //插入位置已知
count++;
upAdjustHeap();
//自底向顶调整堆
}


自底向上调整过程:

private void upAdjustHeap(){

int index = count - 1; //最后一个元素下标

while(index != 0)
{
if(index % 2 == 0) //如果是右节点
{
int pindex = (index - 2)/2;
if(contents[index].compareTo(contents[pindex]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[pindex];
contents[pindex]
= temp;
index
= pindex;
}
else break;
}
else //是左节点
{
int pindex = (index - 1)/2;
if(contents[index].compareTo(contents[pindex]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[pindex];
contents[pindex]
= temp;
index
= pindex;
}
else break;
}
}

}




3,删除操作

public Comparable removeMin() {
// TODO Auto-generated method stub
if(size() == 0)
{
System.out.println(
"堆为空");
return null;
}
Comparable result
= contents[0];
contents[
0] = contents[count-1];
contents[count
-1] = null;
count
--;

downAdjustHeap(
0); //递归的函数,调整以下标0为根的堆
return result;
}


自顶向下调整的过程跟链式差不多,思路都一样,只是换成了数组

private void downAdjustHeap(int index){//自顶往下调整以index下标为根的树
int lindex = 2 * index + 1;
int rindex = 2 * index + 2;

if(contents[lindex] != null && contents[rindex] != null)
{
if(contents[lindex].compareTo(contents[rindex]) < 0)
{
if(contents[lindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[lindex];
contents[lindex]
= temp;
downAdjustHeap(lindex);
}
else return;
}
else
{
if(contents[rindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[rindex];
contents[rindex]
= temp;
downAdjustHeap(rindex);
}
else return;
}
}
else if(contents[lindex] != null && contents[rindex] == null)
{
if(contents[lindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[lindex];
contents[lindex]
= temp;
downAdjustHeap(lindex);
//直接return也可
}
else return;
}
else
return;
}



4,完整清单及测试:

ArrayHeap
package Heap;

import java.util.Iterator;

import Queue.LinkedQueue;

public class ArrayHeap implements HeapADT {

private Comparable[] contents;
private int count; //count不仅表示大小,还表示下一个存储位置,注意堆是一棵完全二叉树

public ArrayHeap()
{
contents
= new Comparable[10];
count
= 0;
}

public ArrayHeap(Comparable ele)
{
contents
= new Comparable[10];
contents[
0] = ele;
count
= 1;
}

public void expand()
{
Comparable[] larger
= new Comparable[contents.length*3];
for(int i =0;i < size();i++)
larger[i]
= contents[i];
contents
= larger;
}


//堆的重要的方法

public void addElement(Comparable element) {
// TODO Auto-generated method stub
if(size() == contents.length)
expand();
contents[count]
= element; //插入位置已知
count++;
upAdjustHeap();
//自底向顶调整堆
}

private void upAdjustHeap(){

int index = count - 1; //最后一个元素下标

while(index != 0)
{
if(index % 2 == 0) //如果是右节点
{
int pindex = (index - 2)/2;
if(contents[index].compareTo(contents[pindex]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[pindex];
contents[pindex]
= temp;
index
= pindex;
}
else break;
}
else //是左节点
{
int pindex = (index - 1)/2;
if(contents[index].compareTo(contents[pindex]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[pindex];
contents[pindex]
= temp;
index
= pindex;
}
else break;
}
}

}


public Comparable removeMin() {
// TODO Auto-generated method stub
if(size() == 0)
{
System.out.println(
"堆为空");
return null;
}
Comparable result
= contents[0];
contents[
0] = contents[count-1];
contents[count
-1] = null;
count
--;

downAdjustHeap(
0); //递归的函数,调整以下标0为根的堆
return result;
}

private void downAdjustHeap(int index){//自顶往下调整以index下标为根的树
int lindex = 2 * index + 1;
int rindex = 2 * index + 2;

if(contents[lindex] != null && contents[rindex] != null)
{
if(contents[lindex].compareTo(contents[rindex]) < 0)
{
if(contents[lindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[lindex];
contents[lindex]
= temp;
downAdjustHeap(lindex);
}
else return;
}
else
{
if(contents[rindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[rindex];
contents[rindex]
= temp;
downAdjustHeap(rindex);
}
else return;
}
}
else if(contents[lindex] != null && contents[rindex] == null)
{
if(contents[lindex].compareTo(contents[index]) < 0)
{
Comparable temp
= contents[index];
contents[index]
= contents[lindex];
contents[lindex]
= temp;
downAdjustHeap(lindex);
//直接return也可
}
else return;
}
else
return;
}


public Comparable findMin() {
// TODO Auto-generated method stub
return contents[0];
}



//迭代器,跟二叉树的数组实现一样

public int size() {
return count;
}

public boolean isEmpty() {
return (size()==0);
}

public Iterator iteratorInorder() {
LinkedQueue queue
= new LinkedQueue();
inorder(
0,queue);
return queue.iterator();
}

private void inorder(int index,LinkedQueue queue){
if(index < contents.length && contents[index] != null)
{
int lindex = 2 * index + 1;
int rindex = 2 * index + 2;

if(lindex < contents.length && contents[lindex] != null)
inorder(lindex,queue);

queue.enqueue(contents[index]);

if(rindex < contents.length && contents[rindex] != null)
inorder(rindex,queue);
}
}


public Iterator PreInorder() {
LinkedQueue queue
= new LinkedQueue();
preorder(
0,queue);
return queue.iterator();
}

private void preorder(int index,LinkedQueue queue){
if(index < contents.length && contents[index] != null)
{
int lindex = 2 * index + 1;
int rindex = 2 * index + 2;

queue.enqueue(contents[index]);

if(lindex < contents.length && contents[lindex] != null)
preorder(lindex,queue);

if(rindex < contents.length && contents[rindex] != null)
preorder(rindex,queue);
}
}

public Iterator PostInorder() {
LinkedQueue queue
= new LinkedQueue();
postorder(
0,queue);
return queue.iterator();
}

private void postorder(int index,LinkedQueue queue){
if(index < contents.length && contents[index] != null)
{
int lindex = 2 * index + 1;
int rindex = 2 * index + 2;

if(lindex < contents.length && contents[lindex] != null)
postorder(lindex,queue);

if(rindex < contents.length && contents[rindex] != null)
postorder(rindex,queue);

queue.enqueue(contents[index]);
}
}




public static void main(String[] args) {
// TODO Auto-generated method stub
ArrayHeap heap = new ArrayHeap();
heap.addElement(
12);
heap.addElement(
17);
heap.addElement(
11);
heap.addElement(
4);
heap.addElement(
10);
heap.addElement(
6);
heap.addElement(
8);
heap.addElement(
22);
heap.addElement(
16);
heap.addElement(
5);
heap.addElement(
2);
heap.addElement(
9);
heap.addElement(
7);
heap.addElement(
20);
heap.addElement(
28);
heap.addElement(
13);
heap.addElement(
15);

System.out.println(
"堆的大小为: " + heap.size());
System.out.println(
"堆为空吗?: " + heap.isEmpty());

System.out.println(
"\n\n中序序列为: ");
Iterator it
= heap.iteratorInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");

System.out.println(
"\n前序序列为: ");
it
= heap.PreInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");

System.out.println(
"\n后序序列为: ");
it
= heap.PostInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");

heap.removeMin();
System.out.println(
"\n\n\n删除最小值后前序序列为: ");
it
= heap.PreInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");

heap.removeMin();
System.out.println(
"\n接着删除最小值后前序序列为: ");
it
= heap.PreInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");

heap.removeMin();
System.out.println(
"\n接着删除最小值后前序序列为: ");
it
= heap.PreInorder();
while(it.hasNext())
System.out.print(it.next()
+ " ");
}

}



还是建的上一篇的堆:




结果:

堆的大小为: 17
堆为空吗?: false


中序序列为:
22  15  16  13  17  4  11  5  10  2  12  7  9  6  20  8  28 
前序序列为:
2  4  13  15  22  16  17  5  11  10  6  7  12  9  8  20  28 
后序序列为:
22  16  15  17  13  11  10  5  4  12  9  7  20  28  8  6  2 


删除最小值后前序序列为:
4  5  13  15  22  17  10  11  16  6  7  12  9  8  20  28 
接着删除最小值后前序序列为:
5  10  13  15  17  11  22  16  6  7  12  9  8  20  28 
接着删除最小值后前序序列为:
6  10  13  15  17  11  22  16  7  9  12  28  8  20


posted @ 2011-05-17 01:07  jinmengzhe  阅读(4578)  评论(0编辑  收藏  举报