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 @   Mars.wang  阅读(164)  评论(0编辑  收藏  举报
编辑推荐:
· AI与.NET技术实操系列:基于图像分类模型对图像进行分类
· go语言实现终端里的倒计时
· 如何编写易于单元测试的代码
· 10年+ .NET Coder 心语,封装的思维:从隐藏、稳定开始理解其本质意义
· .NET Core 中如何实现缓存的预热?
阅读排行:
· 25岁的心里话
· 闲置电脑爆改个人服务器(超详细) #公网映射 #Vmware虚拟网络编辑器
· 零经验选手,Compose 一天开发一款小游戏!
· 通过 API 将Deepseek响应流式内容输出到前端
· AI Agent开发,如何调用三方的API Function,是通过提示词来发起调用的吗
点击右上角即可分享
微信分享提示