您的位置:首页 > 理论基础 > 数据结构算法

数据结构之优先级队列、堆及堆排序

2014-03-06 08:48 357 查看

优先级队列是一个抽象数据类型,它提供删除插入、最大(最小)关键字值数据项的方法,其主要目的是对极值提供便利的访问。
优先级队列可以用有序数组来实现,也可以用队列来实现。

堆,是一种树,由其实现优先级队列的插入删除操作的时间复杂度都是O(logN)。
堆是有如下特点的二叉树:
1.是完全二叉树。即,除了树的最后一层节点不是满的,其他的每一层都必须是满的。
2.堆中的每一个节点都满足堆的条件,即每一个节点的关键字的值都大于或等于其子节点的关键字的值,而小于父节点关键字的值。
3.最大数据项总是在根位置上。
4.一般用数组实现。
5.堆不能有序地遍历所有数据,不能找到特定关键字数据项的位置,也不能移除特定关键字的数据项。
6.要插入的数据项总是先放在数组中的第一个空的位置上,然后再向上筛选它至适当的位置。
7.当从根移除一个数据项时,用数组中的最后一个数据项代替他的位置,然后再向下筛选这个节点到适当的位置。
8.可以更改任意数据项的优先级。首先,更改其关键字,如果增加,则向上筛选,减少,则向下筛选。

堆排序,是一种高效的排序过程,其时间复杂度为O(N*logN).将一个待排序数组依次写入到堆中,写入完毕之后,依次去除根元素(最大元素)写入到数组中,即完成了排序。可以使用同一个数组来存放初始无序的数据、正在排序的数据以及排好序的数据,因此,堆排序不需要额外的空间。(N次插入,N次移除)。
也可以对无序数组的N/2个数据项进行trickDown()操作,而不作N次插入,可使堆排序运行速度更快。

下面是用数组实现的堆以及堆排序:

package test;
public class Heap {
Node2[] heapArray;
int arraySize;// 数组大小
int currentSize;// 数组中实有数据的大小
public Heap(int size) {
arraySize = size;
currentSize = 0;
heapArray = new Node2[arraySize];
}
public boolean isEmpty() {
return currentSize == 0;
}
// 插入
public boolean insert(int key) {
if (currentSize == arraySize)
return false;
Node2 node = new Node2(key);// 创建新节点
heapArray[currentSize] = node;// 将新节点放在数组末尾
trickUp(currentSize++);// 将其向上筛选,同时计数加1
return true;
}
/**
* 节点初始时插入到数组中的空的位置,即最后的位置, 但是如果新插入的节点大于它得到的父节点时,会把堆破坏,
* 因此,需要向上筛选新节点,直到它在一个大于它的父节点之下,在一个小于它的子节点之上。
*/
public void trickUp(int index) {
int parent = (index - 1) / 2;// 父节点的下标
Node2 bottom = heapArray[index];
while (index > 0 && heapArray[parent].idata < bottom.idata) {
heapArray[index] = heapArray[parent];// 向下移动父节点
index = parent;// 将index上移
parent = (parent - 1) / 2;// 父节点的下标给予其父节点
}
heapArray[index] = bottom;
}
// 删除根节点
public Node2 remove() {
Node2 root = heapArray[0];
heapArray[0] = heapArray[--currentSize];
trickDown(0);// 向下筛选
return root;
}
/**
* 将根节点删除之后,需要找到一个适合的节点来替换之
*/
public void trickDown(int index) {
int largerChild;
Node2 top = heapArray[index];
while (index < currentSize / 2) {
int leftChild = index * 2 + 1;
int rightChild = leftChild + 1;
if (rightChild < currentSize
&& heapArray[leftChild].idata < heapArray[rightChild].idata)
largerChild = rightChild;
else
largerChild = leftChild;
if (top.idata >= heapArray[largerChild].idata)
break;
heapArray[index] = heapArray[largerChild];
index = largerChild;
}
heapArray[index] = top;
}
public void show() {
for (int i = 0; i < currentSize; i++) {
if (heapArray[i] != null)
System.out.println(heapArray[i].idata + " ");
else
System.out.println("* ");
}
}
public static void main(String[] args) {
Heap heap = new Heap(6);
heap.insert(12);
heap.insert(23);
heap.insert(4);
heap.insert(2);
heap.insert(8);
heap.show();
Node2 node = heap.remove();
System.out.println("the remove node = " + node.idata);
heap.show();
// 堆排序
Item[] item = { new Item(3), new Item(1), new Item(5), new Item(2),
new Item(7) };
for (int i = 0; i < item.length; i++)
heap.insert(item[i].idata);
for (int i = 0; i < item.length; i++) {
n = heap.remove();
item[i].idata = n.idata;
}
//打印数组
for (int i = 0; i < item.length; i++)
System.out.print(item[i].idata + " . ");
}
}
class Node2 {
int idata;
public Node2(int idata) {
this.idata = idata;
}
}


内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: