java数据结构系列,第七篇:堆

“堆”是一种特殊的二叉树,分为大顶堆:堆顶元素为最大值,子节点小于父节点;小顶堆:堆顶元素为最小值,子节点小于父节点。同时堆是一种完全二叉树,一定要·左右两个子节点都有了才能在子节点上插入子节点。

下面是堆的实现:

import lombok.Data;

@Data

public class Heap
{
    private int[] arr;//数组,用于存储堆中的元素
    private int size;//堆中元素的数量
    private boolean isMaxHeap = true;//是否是大顶堆,默认为大顶堆
    
    /**
     * 构造函数,用于创建指定容量的空堆
     * @param capacity 堆的容量
     * @param isMaxHeap 是否是大顶堆
     */
    public Heap(final int capacity,final boolean isMaxHeap)
    {
        arr = new int[capacity];//初始化数组
        this.isMaxHeap = isMaxHeap;
    }

    public Heap(final int capacity)
    {
        arr = new int[capacity];//初始化数组
    }

    /**
     * 构造函数,用于将指定数组转换为堆
     * @param arr 数组
     * @param isMaxHeap 是否是大顶堆
     */

    public Heap(final int[] arr,final boolean isMaxHeap)
    {
        this.arr = arr;
        this.size = arr.length;
        this.isMaxHeap = isMaxHeap;
        heapify();
    }

    public Heap(final int[] arr)
    {
        this.arr = arr;
        this.size = arr.length;
        heapify();
    }
    
    /**
     * 建堆
     */
    private void heapify()
    {
        //找到非叶子节点  size / 2 - 1
        for (int i = size / 2 - 1; i >= 0; i --)
        {
            down(i);
        }
    }
    /**
     *获取堆顶元素
     * @return 堆顶元素
     */
    public Integer peek()
    {
        return isEmpty() ? null : arr[0];
    }

    /**
     * 删除堆顶元素
     * @return 堆顶元素
     */
    public Integer poll()
    {
        if (isEmpty())
        {
            return null;
        }
        int top = arr[0];
        swap(0,-- size);
        down(0);
        return top;
    }
    /**
     * 删除指定索引处元素
     * @param index 索引
     * @return 堆顶元素
     */
    public Integer poll(final int index)
    {
        if (isEmpty())
        {
            return null;
        }
        int e = arr[index];
        swap(index,-- size);
        down(index);
        return e;
    }
    /**
     * 替换堆顶元素
     * @param replaced 替换的元素
     */

    public void replace(final int replaced)
    {
        arr[0] = replaced;
        down(0);
    }

    /**
     * 向堆中添加元素
     * @param offered 待添加的元素
     */
    public boolean offer(final int offered)
    {
        if (isFull())
        {
            return false;
        }
        up(offered);//添加到堆尾,然后符合条件就上浮
        size ++;
        return true;
    }
    /**
     * 上浮
     * @param offered 待添加的元素
     */
    public void up(final int offered)
    {
        int child = size;
        while (child > 0)
        {
            int parent = (child - 1) / 2;
            if (isMaxHeap)//大顶堆
            {
                if (offered > arr[parent])
                {
                    arr[child] = arr[parent];
                }
                else
                {
                    break;
                }
            }
            else//小顶堆
            {
                if (offered < arr[parent])
                {
                    arr[child] = arr[parent];
                }
                else
                {
                    break;
                }
            }
            child = parent;
        }
        arr[child] = offered;
    }

    /**
     * 下沉
     * @param parent 父节点
     */

    public void down(int parent)
    {
        while (true)
        {
            int left = parent * 2 + 1;
            int right = left + 1;
            if (isMaxHeap) //大顶堆
            {
                int max = parent;
                if (left < size && arr[left] > arr[max])
                {
                    max = left;
                }
                if (right < size && arr[right] > arr[max])
                {
                    max = right;
                }
                if (max != parent)
                {
                    swap(parent,max);
                    parent = max;
                }
                else
                {
                    break;
                }
            }
            else//小顶堆
            {
                int min = parent;
                if (left < size && arr[left] < arr[min])
                {
                    min = left;
                }
                if (right < size && arr[right] < arr[min])
                {
                    min = right;
                }
                if (min != parent)
                {
                    swap(parent,min);
                    parent = min;
                }
                else
                {
                    break;
                }
            }
        }
    }

    /**
     * 交换数组中两个元素
     * @param i 索引i
     * @param j 索引j
     */
    public void swap(final int i,final int j)
    {
        int t = arr[i];
        arr[i] = arr[j];
        arr[j] = t;
    }

    /**
     * 判断堆是否为空
     * @return 如果堆为空,返回true
     */
    public boolean isEmpty()
    {
        return size == 0;
    }
    /**
     * 判断堆是否已满
     * @return 如果堆已满,返回true
     */
    public boolean isFull()
    {
        return size == arr.length;
    }

   
    @Override
    public String toString()
    {
        StringBuilder sb = new StringBuilder();
        sb.append("[");
        for (int i = 0; i < size; i ++)
        {
            sb.append(arr[i]);
            if (i != size - 1)
            {
                sb.append(",");
            }
        }
        sb.append("]");
        return sb.toString();
    }
}

这里的get和set方法我用lombok去构建了,isMaxHeap变量用于标识要创建大顶堆还是小顶堆,默认是个大顶堆。

你可能感兴趣的:(java,数据结构,算法)