最近写java程序的时候,经常用到堆这种数据结构,但是java本身的JDK本没有提供这种数据结构的实现。(栈,队列都有,为什么就不实现一个堆呢……图这种数据结构没有,我是可以理解的,但是堆为什么也没有呢?我就不理解了。有哪位大神知道原因的话,告诉我一下吧0.0)
由于上述原因,我就自己写了一个简单的堆实现。
实现的功能有:堆排序,创建大根堆,创建小根堆,增删改查等基本功能。底层运用的数据结构为:ArrayList。
为了比较方便,以及避免使用java自带的比较器(感觉返回值是一个int类型,1,0,-1什么的,感觉学习成本真高啊……分分钟忘记返回什么,才表示第一个比第二个对象,要“大”),所以自己就在heap类中,重新自己定义了一个简单的比较器接口,通过返回true或者false,告诉heap,是第一个对象“大”,还是第二个对象“大”。
注释的代码,就是一些测试代码,使用的时候,删掉即可。
废话少说,直接上代码:
import java.util.ArrayList;
import java.util.Iterator;
import java.util.List;
public class Heap<E> {
// public static void main(String[] args) {
// Heap<Integer> heap = new Heap<Integer>(new HeapComparator<Integer>() {
//
// @Override
// public boolean isFirstLargerThanSecond(Integer elem1, Integer elem2) {
// return elem1 >= elem2 ? true : false;
//
// }
//
// }, 100);
//
// heap.add(2, false);
// heap.add(10, false);
// heap.add(7, false);
// heap.add(8, false);
// heap.add(9, false);
// heap.add(90, false);
// heap.add(34, false);
// heap.add(23, false);
// heap.add(21, false);
// heap.createMinHeap();
// heap.printHeap();
// heap.createMaxHeap();
// heap.printHeap();
// heap.remove(new Integer(23), true);
// heap.printHeap();
// heap.createMinHeap();
// heap.printHeap();
// }
private List<E> list = null;
private HeapComparator<E> comparator = null;
// 表示当前大根堆还是小根堆。true表示为大根堆,false表示为小根堆
private boolean isMaxHeap = false;
public Heap() {
list = new ArrayList<E>();
}
public Heap(HeapComparator<E> comparator) {
list = new ArrayList<E>();
this.comparator = comparator;
}
public Heap(HeapComparator<E> comparator, int size) {
list = new ArrayList<E>(size);
this.comparator = comparator;
}
/**
* @param e
* @param isMaintain
* 如果未false的话,表示仅仅是添加一个元素,并不会自动去维护堆的关系,所以,这个时候可能已经不再符合堆的结构约束了
* 如果未true的话,就会去维护堆的结构约束。
*/
public void add(E e, boolean isMaintain) {
list.add(e);
if (isMaintain) {
int end = list.size() - 1;
int begin = end / 2;
while (true) {
heapAdjust(begin, end);
end = begin;
if (end == 0) {
break;
}
begin = (end - 1) / 2;
}
}
}
public void addAll(List<E> elems, boolean isMaintain) {
list.addAll(elems);
if (isMaintain) {
heapSort();
}
}
public void remove(E e, boolean isMaintain) {
remove(list.indexOf(e), isMaintain);
}
public void remove(int index, boolean isMaintain) {
if (isMaintain) {
if (index >= list.size()) {
throw new RuntimeException("超出长度了");
}
if (index == list.size() - 1) {
list.remove(index);
return;
}
// 用最后一个替代,然后再重新维护堆结构
list.set(index, list.remove(list.size() - 1));
heapAdjust(index, list.size() - 1);
} else {
list.remove(index);
}
}
private void heapSort() {
int begin = list.size() / 2 - 1;
while (begin >= 0) {
heapAdjust(begin, list.size() - 1);
begin--;
}
}
private void heapAdjust(int begin, int end) {
if (comparator == null) {
throw new RuntimeException("比较器不能为空");
}
boolean flag = true;
if (isMaxHeap) {
flag = true;
} else {
flag = false;
}
int child = begin * 2 + 1;
E temp = null;
int replaceIndex = 0;
while (child <= end) {
replaceIndex = child;
if (child + 1 <= end) {
if (isMaxHeap) {
// 返回更大的对象
flag = comparator.isFirstLargerThanSecond(
list.get(child + 1), list.get(child));
replaceIndex = flag == true ? child + 1 : child;
} else {
flag = comparator.isFirstLargerThanSecond(
list.get(child + 1), list.get(child));
replaceIndex = flag == true ? child : child + 1;
}
}
temp = list.get(begin);
if ((isMaxHeap && comparator.isFirstLargerThanSecond(
list.get(replaceIndex), temp))
|| (!isMaxHeap && !comparator.isFirstLargerThanSecond(
list.get(replaceIndex), temp))) {
list.set(begin, list.get(replaceIndex));
list.set(replaceIndex, temp);
}
begin = replaceIndex;
child = begin * 2 + 1;
}
}
public void createMaxHeap() {
isMaxHeap = true;
heapSort();
}
public void createMinHeap() {
isMaxHeap = false;
heapSort();
}
public void printHeap() {
System.out.println(list);
}
public Iterator<E> getIterator() {
return list.iterator();
}
public E get(int index) {
return list.get(index);
}
/**
* 返回底层的数据结构,方便直接使用原有List提供的功能
*
* @return
*/
public List<E> getUnderlyingStructure() {
return list;
}
public HeapComparator<E> getComparator() {
return comparator;
}
public void setComparator(HeapComparator<E> comparator) {
this.comparator = comparator;
}
interface HeapComparator<E> {
/**
* 第一个元素比第二个大的话,返回true
*
* @param elem1
* @param elem2
* @return
*/
boolean isFirstLargerThanSecond(E elem1, E elem2);
}
}
谢谢~