最大堆---上

普通队列:先进先出
优先队列:出队顺序和入队顺序无关,和优先级相关


二叉堆
二叉堆是一棵完全二叉树(空缺的位置在右下角)
堆中某个节点的值总是不大于其父节点的值(根节点数值最大)

|0| 1 |2|3|4|5|6|7|8|9|10||--|--|--|--|--|--|--||         |  |
数组存储二叉堆

0 1 2 3 4 5 6 7 8 9 10
- 62 41 30 28 16 22 13 19 17 15
parent(i)=i/2
left child(i) = 2*i
right child(i) = 2*i+1
0 1 2 3 4 5 6 7 8 9
62 41 30 28 16 22 13 19 17 15
parent(i)=(i-1)/2
left child(i) = 2*i+1
right child(i) = 2*i+2
package heap;


import java.util.Random;

public class MaxHeap<E extends Comparable<E>> {
    
    
    public Array<E> data;

    public MaxHeap(int capacity) {
    
    
        data = new Array<>(capacity);
    }

    public MaxHeap() {
    
    
        data = new Array<>();
    }

    //返回堆中的元素个数
    public int size() {
    
    
        return data.getSize();
    }

    //返回布尔值,表示堆中是否为空
    public boolean isEmpty() {
    
    
        return data.isEmpty();
    }

    //返回完全二叉树的数组表示中,一个索引所表示的元素的父亲节点的索引
    private int parent(int index) {
    
    
        if (index == 0) {
    
    
            throw new IllegalArgumentException("index-0 doesn't have parent");
        }
        return (index - 1) / 2;
    }

    //返回完全二叉树的数组表示中,一个索引所表示的元素的左孩子节点的索引
    private int leftChild(int index) {
    
    
        return index * 2 + 1;
    }

    //返回完全二叉树的数组表示中,一个索引所表示的元素的右孩子节点的索引
    private int rightChild(int index) {
    
    
        return index * 2 + 2;
    }

    //向堆中添加元素 ,在数组尾部添加,如果比父节点大,则互换位置,依次类推
    public void add(E e) {
    
    
        data.addLast(e);
        siftUp(data.getSize() - 1);
    }

    private void siftUp(int k) {
    
    
        while (k > 0 && data.get(parent(k)).compareTo(data.get(k)) < 0) {
    
    
            data.swap(k, parent(k));
            k = parent(k);
        }
    }

    //看堆中最大的是谁
    public E findMax() {
    
    
        if (data.getSize() == 0)
            throw new IllegalArgumentException("Can not findMax when heap is empty");
        return data.get(0);
    }

    //向堆中取出元素(最大元素)把最后一个元素补充到堆顶,和孩子中最大的元素互换位置
    public E extractMax() {
    
    
        E ret = findMax();
        data.swap(0, data.getSize() - 1);
        data.removeLast();
        shifDown(0);
        return ret;
    }

    private void shifDown(int k) {
    
    
        //有左孩子
        while (leftChild(k) < data.getSize()) {
    
    
            int j = leftChild(k);
            //有右孩子,并且右孩子比左孩子大
            if (j + 1 < data.getSize() && data.get(j + 1).compareTo(data.get(j)) > 0) {
    
    
                j = rightChild(k);
                //data[j]是leftChild和rightChild中的最大值
                if (data.get(k).compareTo(data.get(j)) >= 0)
                    break;
                data.swap(k, j);
                k = j;
            }
        }
    }

    public static void main(String[] args) {
    
    

        int n = 100;
        MaxHeap<Integer> maxHeap = new MaxHeap<>();
        Random random = new Random();
        for (int i = 0; i < n; i++) {
    
    
            maxHeap.add(random.nextInt(Integer.MAX_VALUE));

        }
        int[] arr = new int[n];
        for (int i = 0; i < n; i++) {
    
    
            arr[i] = maxHeap.extractMax();
        }
        for (int i = 0; i < n; i++) {
    
    
            if (arr[i-1]<arr[i])
                throw new IllegalArgumentException("Error");
        }
        System.out.println("test MaxHeap completed");

    }


}

array

package heap;

public class Array<E>{
    
    
    private E[] data;
    private int size;//记录元素个数

    //构造函数,用户创建数组开辟的空间
    public Array(int capacity) {
    
    
//        new 一个E类型的数组
        data =(E[]) new Object[capacity];
        size = 0;
    }

    //用户不传参时,默认开辟空间10
    public Array() {
    
    
        this(10);
    }

    //获取数组中元素个数
    public int getSize() {
    
    
        return size;
    }

    //获取空间大小
    public int getCapacity() {
    
    
        return data.length;
    }

    //判断数组是否为空
    public boolean isEmpty() {
    
    
        return size == 0;
    }

    //在数组最后添加元素2-3
    public void addLast(E e) {
    
    
//        if (size == data.length)
//            throw new IllegalArgumentException("Addlast failed.heap.Array is full");
//        data[size] = e;
//        size++;
        add(size,e);
    }

    //在首位置添加元素
    public void addFirst(E e){
    
    
        add(0,e);
    }

    //指定位置添加元素
    //元素从后往前挪把指定位置空出来
    public void add(int index,E e){
    
    
        if (size == data.length){
    
    
            resize(data.length * 2);
        }
        if (index<0||index>size)
            throw new IllegalArgumentException("Add failed.Require index>=0 and index<=size");
        for (int i=size-1;i>=index;i--){
    
    
            data[i+1]=data[i];
        }
        data[index]=e;
        size++;
    }

    private void resize(int capacity) {
    
    
        E[] newData = (E[]) new Object[capacity];
        for (int i = 0; i < size; i++) {
    
    
            newData[i] = data[i];
        }
        data=newData;

    }

    //获取index索引的位置
    public E get(int index){
    
    
        if (index<0||index>=size)
            throw new IllegalArgumentException("Add failed.Require index>=0 and index<=size");
        return data[index];
    }
    public E getLast(){
    
    
        return get(size-1);
    }
    public E getFirst(){
    
    
        return get(0);
    }
    //更新数组元素
    public void set(int index,E e){
    
    
        if (index<0||index>=size)
            throw new IllegalArgumentException("Add failed.Require index>=0 and index<=size");
        data[index]=e;
    }

    //是否包含某元素
    public boolean contains(E e){
    
    
        for (int i = 0; i < size; i++) {
    
    
            if (e.equals(data[i]))
                return true;
        }
        return false;
    }

    //返回所要查找的元素的索引
    public int find(E e){
    
    
        for (int i = 0; i < size; i++) {
    
    
            if (e.equals(data[i]))
                return i;
        }
        return -1;
    }

    //删除索引处的某个元素并返回,将索引之后的元素向前移动
    public E remove(int index){
    
    
        if (index<0||index>size)
            throw new IllegalArgumentException("Add failed.Require index>=0 and index<=size");

        E result=data[index];
        for (int i = index+1; i < size; i++) {
    
    
            data[i-1]=data[i];
        }
        size--;
        if (size==data.length/4&&data.length/2!=0){
    
    
            resize(data.length/2);
        }
        return result;
    }

    //删除头元素
    public E removeFirst(){
    
    
        return remove(0);
    }
    //删除最后一个元素
    public E removeLast(){
    
    
        return remove(size-1);
    }

    //删除某个元素
    public void removeElement(E e){
    
    
        int index = find(e);
        if (index!=-1)
            remove(index);
    }
    //交换元素
    public void swap(int i,int j){
    
    
        if (i<0||i>=size||j<0||j>=size){
    
    
            throw new IllegalArgumentException("Index is illegal");
        }
        E t =data[i];
        data[i] = data[j];
        data[j] = t;
    }
    @Override
    public String toString() {
    
    
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(String.format("heap.Array:size=%d,capacity =%d\n",size,data.length));
        stringBuilder.append("[");
        for (int i=0;i<size;i++){
    
    
            stringBuilder.append(data[i]);
            if (i!=size-1)
                stringBuilder.append(",");
        }
        stringBuilder.append("]");
        return stringBuilder.toString();
    }
}

猜你喜欢

转载自blog.csdn.net/weixin_45010894/article/details/108545779