手撕经典数据结构——堆

堆的函数主要有,插入,删除,查看堆顶元素。

建堆主要依靠插入函数。

我们需要定义一个数组,int类型长度和int类型容量。

在操作过程中我们需要用到查看父亲节点函数,查看左孩子节点函数,查看右孩子节点函数和交换元素位置函数。

除了上面之外,插入和删除两个操作需要涉及到堆的元素上浮函数和元素下沉函数。

所有信息如下所示:
代码:

java 复制代码
package org.example.heap;

import java.util.*;

public class Heap {
    private int[] heap;
    private int size;
    private int capacity;

    public Heap(int capacity){
        this.capacity = capacity;
        this.size = 0;
        this.heap = new int[capacity];
    }

    //0->1->2
    public int parent(int index){
        return (index - 1) / 2;
    }

    public int leftChild(int index){
        return index * 2 + 1;
    }

    public int rightChild(int index){
        return index * 2 + 2;
    }

    public void swap(int i,int j){
        int temp = heap[i];
        heap[i] = heap[j];
        heap[j] = temp;
    }

    /**
     * 上移
     */
    public void heapUp(){
        int index = size -1 ;
        //一直可以移动到堆顶
        while(index>0&&heap[index]>heap[parent(index)]){
            swap(index,parent(index));
            index = parent(index);
        }
    }

    /**
     * 下沉
     */
    public void heapDown(){
        int index = 0;
        //有一个孩子说明就不是根节点,没必要左右节点都进行判断,因为左节点没有右节点一定没有,左节点的优先级要高于右节点
        //这样子代码冗余度过高,我们考虑通过预先确定较大值的下标来简化代码
//        while(leftChild(index)<size){
//            int left = leftChild(index);
//            int right = rightChild(index);
//            if(right<size){
//                int maxNum = Math.max(heap[left],heap[right]);
//                if(heap[index]>maxNum)break;
//                //把大的拿个换上来
//                if(heap[left]<heap[right]){
//                    swap(index,right);
//                    index = rightChild(index);
//                }else {
//                    swap(index,left);
//                    index = leftChild(index);
//                }
//            }else{
//                if(heap[index]>heap[left])break;
//                swap(index,left);
//                index = leftChild(index);
//            }
//        }
        while(leftChild(index)<size){
            int left = leftChild(index);
            int right = rightChild(index);
            int min = left;
            if(right<size&&heap[right]>heap[left])
                min = right;
            if(heap[min]<heap[index])break;
            else{
                swap(index,min);
                index = min;
            }
        }
    }

    /**
     * 插入元素
     */
    public void insert(int value) {
        //给堆设置一个阈值,如果堆内的元素达到了总容量的0.6自动触发扩容
        size++;
        if(size>=capacity*0.6){
            //进行堆扩容
            int[] temp = new int[capacity*2];
            if (capacity >= 0) System.arraycopy(heap, 0, temp, 0, capacity);
            heap = temp;
            capacity*=2;
        }
        heap[size-1] = value;
        heapUp();
    }

    /**
     * 移除堆顶元素
     */
    public void removeTop(){
        if(size==0)
            throw new IllegalStateException("堆是空的");
        int min = heap[0];
        heap[0] = heap[size-1];
        size--;
        heapDown();
    }

    /**
     * 获取堆顶元素
     */
    public int getTop(){
        if(size>0)
            return heap[0];
        else
            throw new IllegalStateException("堆中无元素");
    }
}

我们测试一下:

java 复制代码
package org.example.heap;

public class HeapTest {
    public static void main(String[] args) {
        Heap heap = new Heap(10);
        heap.insert(2);
        heap.insert(1);
        heap.insert(3);
        heap.insert(2);
        heap.insert(5);
        //5
        System.out.println(heap.getTop());
        heap.removeTop();
        //3
        System.out.println(heap.getTop());
        heap.removeTop();
        //2
        System.out.println(heap.getTop());
        heap.removeTop();
        //2
        System.out.println(heap.getTop());
        heap.removeTop();
        //1
        System.out.println(heap.getTop());
    }
}

结果符合预期

相关推荐
晨非辰2 小时前
数据结构排序系列指南:从O(n²)到O(n),计数排序如何实现线性时间复杂度
运维·数据结构·c++·人工智能·后端·深度学习·排序算法
小曹要微笑2 小时前
STM32H7系列全面解析:嵌入式性能的巅峰之作
c语言·stm32·单片机·嵌入式硬件·算法
寻星探路2 小时前
JavaSE重点总结后篇
java·开发语言·算法
松涛和鸣4 小时前
14、C 语言进阶:函数指针、typedef、二级指针、const 指针
c语言·开发语言·算法·排序算法·学习方法
yagamiraito_6 小时前
757. 设置交集大小至少为2 (leetcode每日一题)
算法·leetcode·go
星释6 小时前
Rust 练习册 57:阿特巴什密码与字符映射技术
服务器·算法·rust
星期天26 小时前
3.0 C语⾔内存函数:memcpy memmove memset memcmp 数据在内存中的存储:整数在内存中的存储 ⼤⼩端字节序和字节序判断
c语言·数据结构·进阶·内存函数·数据内存存储
无敌最俊朗@6 小时前
力扣hot100-141.环形链表
算法·leetcode·链表
WWZZ20258 小时前
快速上手大模型:深度学习10(卷积神经网络2、模型训练实践、批量归一化)
人工智能·深度学习·神经网络·算法·机器人·大模型·具身智能
sali-tec9 小时前
C# 基于halcon的视觉工作流-章62 点云采样
开发语言·图像处理·人工智能·算法·计算机视觉