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

数据结构与算法之优先队列<九>

2017-04-07 17:55 459 查看
什么是优先队列

快速得找到元素的最大或最小值。为了实现这种数据结构

优先队列便孕育而生。优先队列或ADT是一种数据结构,支持插入和删除最小值或最大值并返回最大值或最小值得操作。

优先队列的应用

1.数据压缩(赫夫曼编码)

2.最短路径

3.最小生成树

4.选择问题:查找第K个最小元素

优先队列的实现

1.有序/无序数组实现

2.有序/无序链表实现

3.二叉树实现

4.二叉堆实现

主要介绍二叉堆的实现

二叉堆是一棵具有特殊性质的二叉树。

基本要求是所有节点必须大于或等于(小于或等于)其孩子节点

并且应该是一棵完全二叉树

二叉堆的实现

/*
* 优先队列是至少允许下列两种操作的数据结构
* insert(插入) deleteMin(删除最小)
* 优先队列的工作是 找出 返回 删除 优先队列中的最小或最大元素
*
* 完全二叉堆实现优先队列
* 利用完全二叉树的紧凑性将完全二叉树转化为数组形式
*/
public class BinaryHeap<T extends Comparable<? super T>> {
// 堆
private T[] heap;
// 当前大小
private int currentSize;
// 默认大小
private final static int DEFAULT_SIZE = 10;

public BinaryHeap() {
this(DEFAULT_SIZE);
}

// 打印二叉堆
public void printHeap() {
for (int i = 0; i < currentSize; i++)
System.out.print(this.heap[i] + ",");
}

@SuppressWarnings("unchecked")
public BinaryHeap(int size) {
heap = (T[]) new Comparable[size];
}

// 将一个数组转化为二叉堆
@SuppressWarnings("unchecked")
public BinaryHeap(T[] items) {
currentSize = items.length;
heap = (T[]) new Comparable[(currentSize + 2) * 11 / 10];
System.arraycopy(items, 0, heap, 0, items.length);
bulidHeap();
}

/*
* 对外开放的方法
*/

// 插入堆
public void insert(T t) {
// 数据临界 扩一倍
if (currentSize == heap.length)
enlargeArray(heap.length * 2);
// 当前数量加一
currentSize++;
// 插入节点的序号
int i = currentSize - 1;
while (i > 0 && t.compareTo(heap[(i - 1) / 2]) > 0) {
// 插入数据大于其父节点的数据
heap[i] = heap[(i - 1) / 2];
// 下一个父节点
i = (i - 1) / 2;
}
heap[i] = t;
}

// 找到最大值
public T findMax() {
if (currentSize > 0)
return heap[0];
return null;

}

// 删除最大值
public T deleteMax() {
T t = null;
if (currentSize > 0) {
t = heap[0];
// 将最后一个元素替代第一个
heap[0] = heap[currentSize - 1];
currentSize--;
percolateDown(0);
}
return t;
}

/*
* 私人方法
*/

// 下滤 (先找到孩子的最大值在与小于孩子的父节点互换)
private void percolateDown(int hole) {
// 判断节点是否有孩子
int left = hole * 2 + 1;
T temp;
// 如果左孩子存在
if (left < currentSize) {
// 如果右孩子存在
if (left + 1 < currentSize) {
// 若右孩子大于左孩子互换
if (heap[left + 1].compareTo(heap[left]) > 0) {
temp = heap[left + 1];
heap[left + 1] = heap[left];
heap[left] = temp;
}
}
// 如果左节点大于父节点 互换
if (heap[left].compareTo(heap[hole]) > 0) {
temp = heap[hole];
heap[hole] = heap[left];
heap[left] = temp;
}
}
}

// 建立二叉堆
public void bulidHeap() {
// 调整所有节点 (currentSize表示当前堆中元素个数)
for (int i = (currentSize - 2) / 2; i >= 0; i--) {
percolateDown(i);
}
}

// 动态扩充数组变为原来的两倍
@SuppressWarnings("unchecked")
private void enlargeArray(int newSize) {
// 保存旧数据
T[] temp = heap;
// 扩一倍
heap = (T[]) new Comparable[2 * heap.length];
// 导入旧数据
System.arraycopy(temp, 0, heap, 0, temp.length);
}
}


至此,优先队列的基础介绍完毕。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息