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

[数据结构] 二叉堆,堆排序,优先级队列

2017-04-29 10:45 337 查看

前言

最近在看算法导论中的第六章堆排序,忍不信手又痒了起来,利用零散时间,参照书里的思路,利用java实现了一些堆的基本操作,供小白参考。

有时间会整理堆的介绍和一些性质,这事后话。

我也是菜鸟一个,代码中难免有bug,也请大手子交流与指出

源码

package com.jianglei;

import java.util.ArrayList;
import java.util.List;

/**
* 参照算法导论实现的二叉堆结构
* Created by Administrator on 2017/5/3.
*/
public class HeapSort<E extends Comparable<E>> {
/**
* 用ArrayList作为空器的底层存储
*/
private List<E> elements = new ArrayList<>();

/**
* 堆的元素数量
* @return
*/
public int size(){
return elements.size();
}

/**
* 在堆的末尾添加元素(测试用)
* @param e
* @return
*/
public boolean add(E e){
return elements.add(e);
}

/**
* 返回此索引的左孩子的索引
* @param i
* @return
*/
private int left(int i){
int leftIndex = 2 * i + 1;
return leftIndex < size() ? leftIndex : -1;
}

/**
* 返回此索引的右孩子的索引,如果为-1表示没有
* @param i
* @return
*/
private int right(int i){
int rightIndex = 2 * i + 2;
return rightIndex < size() ? rightIndex : -1;
}

/**
* 返回此索引的双亲结点的索引,如果为-1表示没有
* @param i
* @return
*/
private int parent(int i){
int parentIndex = (i - 1) / 2;
return parentIndex < 0 ? -1 : parentIndex;
}

public String toString(){
return elements.toString();
}

/**
* 假设此节点的左子树,和右子树都满足二叉堆的性质,而以此索引为节点可能不满足二叉堆的性质,
* 此方法调整该节点为根的树满足二叉堆的性质
* @param i
*/
public void maxHeapify(int i){
int largest = i;
int left = left(i);
int right = right(i);
if(left != -1 && less(i, left)){
largest = left;
}
if(right != -1 && less(largest, right)){
largest = right;
}

if(largest != i){
exch(i, largest);
maxHeapify(largest);
}
}

/**
* 将随机分配的列表调整为满足二叉堆性质的列表
*/
public void buildMaxHeap(){
int lastInnerNodeIndex = lastInnerNodeIndex();
for(int i = lastInnerNodeIndex; i >= 0; i--){
maxHeapify(i);
}

}

/**
* 堆排序,此实现与算法导论里的描述有差异,并不推荐作为参考
* @return
*/
public List<E> heapSort(){
int end = size() - 1;
List<E> list =new ArrayList<>();
buildMaxHeap();
for(int i = end; i >= 1; i--,end--){
exch(0,end);
E e = remove(end);
list.add(0, e);
maxHeapify(0);

}

return list;
}

//最大优先级队列的一些操作

/**
* 返回值最大的的节点
* @return
*/
public E heapMaximum(){
return get(0);
}

/**
* 删除并返回值最大的节点,并重新构造最大堆
* @return
*/
public E heapExtractMax(){
if(size() == 0){
throw new IndexOutOfBoundsException();
}else if(size() == 1){
return get(0);
}else{
E max = get(0);
set(0, remove(size() - 1));
maxHeapify(0);
return max;
}
}

/**
* 将某节点的值增大,并重新构造最大堆
* 如果key值比原节点值小则抛出异常{@code IllegalArgumentException}
* @param i
* @param key
* @throws IllegalArgumentException
*/
public void increaseKey(int i, E key){
if(key.compareTo(get(i)) < -1){
throw new IllegalArgumentException("key is less than now");
}
elements.set(i, key);
while (i > 0 && elements.get(parent(i)).compareTo(elements.get(i)) < 0){
exch(i, parent(i));
i = parent(i);
}
}

/**
* 添加一个节点,并重新构造最大堆,将此节点调用至相应的位置
* @param key
*/
public void maxHeapInsert(E key){
add(key);
int i = size() - 1;
while (i > 0 && elements.get(parent(i)).compareTo(elements.get(i)) < 0){
exch(i, parent(i));
i = parent(i);
}
}

//一些辅助函数

public E remove(int index){
return elements.remove(index);
}
private int lastInnerNodeIndex(){
return size() / 2;
}

private void exch(int i, int j){
E temp = get(i);
set(i, get(j));
set(j, temp);

}
public void set(int i, E e){
elements.set(i, e);
}
public E get(int i){
E e = elements.get(i);
return e;
}
public boolean less(int i, int j){
E e = get(i);
E e1 = get(j);

int compRes = e.compareTo(e1);
return compRes < 0 ? true : false;

}

}


参考

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