java实现小顶堆,堆是优先队列的底层数据结构
import com.google.common.collect.Lists; import lombok.Data; import lombok.NoArgsConstructor; import java.util.ArrayList; import java.util.List; import java.util.Random; /** * 如果根节点所在下标是0,则父节点下标i,左孩子下标2i+1,右孩子2i+2 * 如果根节点所在下标是1,则父节点下标i,左孩子下标2i,右孩子2i+1 * 因为我们用的是ArrayList,所有根节点下标为0 * * @param <T> */ @Data @NoArgsConstructor public class MHeap<T extends Comparable<T>> { private final int capacity = 100; private List<T> items = new ArrayList<T>(capacity); @Override public String toString() { return "MHeap{" + "items=" + items + '}'; } /** * 传入list构建堆 * * @param items */ public MHeap(List<T> items) { for (T item : items) { insert(item); } } public boolean isEmpty() { return items.isEmpty(); } public void insert(T data) { items.add(data); floatUp(data); } /** * 上浮:指定元素与父节点做比较,小于父节点就上浮, * 一直上浮到它应在的位置 */ private void floatUp(T data) { int child = items.size() - 1; int parent = (child - 1) / 2; //小则上浮 while (data.compareTo(items.get(parent)) < 0) { items.set(child, items.get(parent)); child = parent; parent = parent / 2; if (child == 0) { break; } } items.set(child, data); } /** * 1.先拿到最小值,暂存等待返回 * 2.获取最后一个节点last的数据e * 3.e数据放在根节点可能不一定最小,对比根的孩子节点逐级下沉,让根最小的孩子上浮 * 4.把原来最后的节点last删掉 * * @return */ public T pop() { T t = items.get(0); int last = items.size() - 1; T e = items.get(last); sinkDown( e); items.remove(last); return t; } /** * 下沉:根节点下沉到它应该的位置 */ private void sinkDown(T data) { int size = items.size(); //当前根 int parent = 0; //当前根的左孩子 int child = parent * 2 + 1; //循环条件是还没有越界 while (child < size) { //判断根是否有右孩子,假如右孩子更小,拿到更小的孩子,等待与根节点对比 if (child + 1 < size && items.get(child + 1).compareTo(items.get(child)) < 0) { child = child + 1; } //父节点小于最小的子节点,则不用动了 if (data.compareTo(items.get(child)) < 0) { break; } //父节点大于最小的孩子,则最小的孩子上浮到根节点 items.set(parent, items.get(child)); parent = child; child = parent * 2 + 1; } items.set(parent, data); } public static void main(String[] args) { List<Integer> ints = Lists.newArrayList(); Random rand = new Random(); for (int i = 10; i > 0; i--) { int i1 = rand.nextInt(100); ints.add(i1); } System.out.println(ints); MHeap<Integer> m = new MHeap<>(ints); while (!m.isEmpty()) { System.out.println(m.pop()); } } }