八大数据结构——堆(八)

import java.util.NoSuchElementException;

//实现一个最大堆
public class MaxHeap<Type> {
    private Type[] elements;//存储数据单元
    private int size;//当前指针位置
    private static final int Default_size = 10;//默认大小

    public MaxHeap() {
        elements = (Type[]) new Object[Default_size];
        size = 0;
    }

    public MaxHeap(int sz) {
        elements = (Type[]) new Object[sz];
        size = 0;
    }

    //    将一个已有数组堆化,即先找到最后一个非叶子节点,然后逐个下沉,一直到堆顶。
    //    最后一个非叶子节点的子节点,就是size-1,知道子节点后,通过parent()方法找父节点,就找到它了。
    public MaxHeap(Type[] data) {
        elements = data;
        size = data.length;
        for (int i = parent(size - 1); i >= 0; i--) {
            floatDown(i);
        }
    }

    public void clear() {
        size = 0;
    }

    public int size() {
        return size;
    }

    public boolean isEmpty() {
        return size == 0;
    }

    //  子节点找父节点,左子节点:parent = (left-1)/2;,右子节点:parent = (right-2)/2;
    //  这里是指索引。因为int只保留整数,所以两个式子可以合并为一个。
    private int parent(int index) {
        if (index == 0) {
            throw new IllegalArgumentException("该节点为根节点");
        }
        return (index - 1) / 2;
    }

    //    父节点找子节点,左子节点:left = parent*2+1;右子节点right = parent*2 + 2;这里是指索引。
    private int leftChild(int index) {
        return index * 2 + 1;
    }

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

    //    插入数据
    public void add(Type val) {
        if (elements.length == size) {
            Type[] old = elements;
            elements = (Type[]) new Object[size * 2];
            for (int i = 0; i < size; i++) {
                elements[i] = old[i];
            }
        }
        elements[size] = val;
        size++;
        floatUp(size - 1);
    }

    //    上浮数据,调整堆结构,如果子节点元素大于父节点元素,则交换。暂时用toString后的compareTo方法比较。
    private void floatUp(int index) {
        while (index > 0 && 0 > elements[parent(index)].toString()
                .compareTo(elements[index].toString())) {
            Type t = elements[parent(index)];
            elements[parent(index)] = elements[index];
            elements[index] = t;
            index = parent(index);
        }
    }

    //    提取堆顶
    public Type extractMax() {
        if (size == 0) {
            throw new NoSuchElementException();
        }
        Type max = elements[0];
        elements[0] = elements[size - 1];
        size--;
        floatDown(0);
        return max;
    }

    //    下沉数据,把父节点与子节点比较,看是否符合要求,即父节点大于子节点,不符合则进行交换。
    private void floatDown(int index) {
        while (leftChild(index) < size) {
            int temp = leftChild(index);
            if (rightChild(index) < size && 0 >
                    elements[leftChild(index)].toString().compareTo(
                            elements[rightChild(index)].toString())) {
                //   左子节点小于右子节点
                temp++;
            }
            if (0 < elements[temp].toString()
                    .compareTo(elements[index].toString())) {
                //            子节点大于父节点
                Type t = elements[index];
                elements[index] = elements[temp];
                elements[temp] = t;
                index = temp;
            } else {
                //          子节点小于等于父节点,下沉结束
                break;
            }
        }
    }

    //    替换堆顶,然后进行下沉继续保持结构
    public Type replace(Type val) {
        if (size == 0) {
            throw new NoSuchElementException();
        }
        Type max = elements[0];
        elements[0] = val;
        floatDown(0);
        return max;
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值