java实现堆

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());
        }
    }
}

 

posted @ 2021-10-09 13:21  Mars.wang  阅读(156)  评论(0编辑  收藏  举报