12、最大堆和最小堆 的实现(下篇)

一、简单介绍

1、我们前面已经用最大堆得例子,已经讲了所有的最大堆的操作。

里面包过添加操作,用到我们shiftUp()操作。

包过删除操作,我们用到sihftDown操作。

然后就是通过一个数组,我们能够构建一个堆。也就是我们说的heapify 操作。

2、最小堆的操作和上面的类似,只是比较的时候不一样。

二、所有的代码实现

1、最大堆的实现

package com.ipp.demo;

public class MaxHeap<T extends Comparable<T>> {

    //定义一个数组
    private Array<T> data;


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


    public  MaxHeap(){
        this(10);
    }
   //把一个数组直接转化成最大堆。  heapify
    public  MaxHeap(T []res){
        data=new Array<T>(res.length);
        //我们从最后一个元素的父元素开始进行shiftDown操作
        for (int  i=getParent(res.length-1);i>=0;i--){
                  shiftDown(i);
        }
    }

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

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

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

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


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

    // 向堆中添加元素
    public void add(T e) {
        int index = size();
        data.addLast(e);  //最堆中最后添加元素。
        shiftUp(index);
    }

    //向上shiftup
    private void shiftUp(int index) {
        while (index > 0 && data.get(getParent(index)).compareTo(data.get(index)) < 0) {
            data.swap(index, getParent(index));
            index = getParent(index);
        }
    }

    // 看堆中的最大元素

    public T getMax() {
        if (size() == 0) {
            throw new IllegalArgumentException("堆中没有数据");
        }
        return data.get(0);
    }

    public T extractMax() {
        T res = getMax();
        data.swap(0,size()-1);   //交换第一个元素和最后一个元素
        data.removeLast(); //移除最后一个元素。
        shiftDown(0); //shiftDown第一个元素
        return res;
    }


    private void shiftDown(int i) {
        while(getLeftChild(i)<size()){   //首先默认
             int  j=getLeftChild(i);   //j 表示的是要找的元素
             if(j+1<size()&&data.get(j).compareTo(data.get(j+1))<0){
                 j++;
             }
             if(data.get(i).compareTo(data.get(j))>0){
                 break;
             }
             data.swap(i,j);  //交换元素
             i=j;  //调准顺序继续向下寻找
        }
    }

    public static void main(String[] args) {


    }
}

2、最小堆的实现

package com.ipp.demo;

public class MinHeap<T extends Comparable<T>> {
    //定义一个数组
    private Array<T> data;

    public MinHeap(int capciaty) {
        data = new Array<>(capciaty);
    }


    public  MinHeap(){
        this(10);
    }
    //把一个数组直接转化成最大堆。  heapify
    public  MinHeap(T []res){
        data=new Array<T>(res.length);
        //我们从最后一个元素的父元素开始进行shiftDown操作
        for (int  i=getParent(res.length-1);i>=0;i--){
            shiftDown(i);
        }
    }

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

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

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

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


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

    // 向堆中添加元素
    public void add(T e) {
        int index = size();
        data.addLast(e);  //最堆中最后添加元素。
        shiftUp(index);
    }

    //向上shiftup
    private void shiftUp(int index) {
        while (index > 0 && data.get(getParent(index)).compareTo(data.get(index)) >0) {
            data.swap(index, getParent(index));
            index = getParent(index);
        }
    }

    // 看堆中的最大元素

    public T getMin() {
        if (size() == 0) {
            throw new IllegalArgumentException("堆中没有数据");
        }
        return data.get(0);
    }

    public T extractMin() {
        T res = getMin();
        data.swap(0,size()-1);   //交换第一个元素和最后一个元素
        data.removeLast(); //移除最后一个元素。
        shiftDown(0); //shiftDown第一个元素
        return res;
    }


    private void shiftDown(int i) {
        while(getLeftChild(i)<size()){   //首先默认
            int  j=getLeftChild(i);   //j 表示的是要找的元素
            if(j+1<size()&&data.get(j).compareTo(data.get(j+1))>0){
                j++;
            }
            if(data.get(i).compareTo(data.get(j))<0){  //如果以前的元素更小 就算了
                break;
            }
            data.swap(i,j);  //交换元素
            i=j;  //调准顺序继续向下寻找
        }
    }


}

3、利用堆实现优先队列的实现

package com.ipp.demo;

public class PriorityQueue<E  extends  Comparable<E>>  implements  Queue<E>{

    private   MaxHeap<E>  maxHeap;

    public PriorityQueue() {
        maxHeap=new MaxHeap<E>();
    }

    @Override
    public int getSize() {
        return maxHeap.size();
    }

    @Override
    public boolean isEmpty() {
        return maxHeap.isEmpty();
    }

    @Override
    public void enqueue(E e) {
          maxHeap.add(e);
    }

    @Override
    public E dequeue() {
        return maxHeap.extractMax();
    }

    @Override
    public E getFront() {
        return maxHeap.getMax();
    }


    public static void main(String[] args) {
        PriorityQueue   quque=new PriorityQueue();
        quque.enqueue(10);
        quque.enqueue(100);
        quque.enqueue(40);
        System.out.println(  quque.dequeue());
        System.out.println(  quque.dequeue());
        System.out.println(quque.getSize());
    }
}

4、里面用到的底层数组的实现

package com.ipp.demo;

public class Array<E> {

    private E[] data;
    private int size;

    // 构造函数,传入数组的容量capacity构造Array
    public Array(int capacity){
        data = (E[])new Object[capacity];
        size = 0;
    }

    // 无参数的构造函数,默认数组的容量capacity=10
    public Array(){
        this(10);
    }

    // 获取数组的容量
    public int getCapacity(){
        return data.length;
    }

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

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

    // 在index索引的位置插入一个新元素e
    public void add(int index, E e){

        if(index < 0 || index > size)
            throw new IllegalArgumentException("Add failed. Require index >= 0 and index <= size.");

        if(size == data.length)
            resize(2 * data.length);

        for(int i = size - 1; i >= index ; i --)
            data[i + 1] = data[i];

        data[index] = e;

        size ++;
    }

    // 向所有元素后添加一个新元素
    public void addLast(E e){
        add(size, e);
    }

    // 在所有元素前添加一个新元素
    public void addFirst(E e){
        add(0, e);
    }

    // 获取index索引位置的元素
    public E get(int index){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Get failed. Index is illegal.");
        return data[index];
    }

    // 修改index索引位置的元素为e
    public void set(int index, E e){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Set failed. Index is illegal.");
        data[index] = e;
    }

    // 查找数组中是否有元素e
    public boolean contains(E e){
        for(int i = 0 ; i < size ; i ++){
            if(data[i].equals(e))
                return true;
        }
        return false;
    }

    // 查找数组中元素e所在的索引,如果不存在元素e,则返回-1
    public int find(E e){
        for(int i = 0 ; i < size ; i ++){
            if(data[i].equals(e))
                return i;
        }
        return -1;
    }

    // 从数组中删除index位置的元素, 返回删除的元素
    public E remove(int index){
        if(index < 0 || index >= size)
            throw new IllegalArgumentException("Remove failed. Index is illegal.");

        E ret = data[index];
        for(int i = index + 1 ; i < size ; i ++)
            data[i - 1] = data[i];
        size --;
        data[size] = null; // loitering objects != memory leak

        if(size == data.length / 4 && data.length / 2 != 0)
            resize(data.length / 2);
        return ret;
    }

    // 从数组中删除第一个元素, 返回删除的元素
    public E removeFirst(){
        return remove(0);
    }

    // 从数组中删除最后一个元素, 返回删除的元素
    public E removeLast(){
        return remove(size - 1);
    }

    // 从数组中删除元素e
    public void removeElement(E e){
        int index = find(e);
        if(index != -1)
            remove(index);
    }

    @Override
    public String toString(){

        StringBuilder res = new StringBuilder();
        res.append(String.format("Array: size = %d , capacity = %d\n", size, data.length));
        res.append('[');
        for(int i = 0 ; i < size ; i ++){
            res.append(data[i]);
            if(i != size - 1)
                res.append(", ");
        }
        res.append(']');
        return res.toString();
    }

    // 将数组空间的容量变成newCapacity大小
    private void resize(int newCapacity){

        E[] newData = (E[])new Object[newCapacity];
        for(int i = 0 ; i < size ; i ++)
            newData[i] = data[i];
        data = newData;
    }



    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;
    }
}

 

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
可以通过下面的代码实现最小最大堆: ```c #include <stdio.h> #include <stdlib.h> #define MAX_HEAP_SIZE 100 typedef struct Heap { int* data; int size; } Heap; Heap* create_heap() { Heap* heap = (Heap*)malloc(sizeof(Heap)); heap->data = (int*)malloc(sizeof(int) * MAX_HEAP_SIZE); heap->size = 0; return heap; } void swap(int* a, int* b) { int temp = *a; *a = *b; *b = temp; } void down_adjust(Heap* heap, int index, int is_min_heap) { int left = index * 2 + 1; int right = index * 2 + 2; int maxmin = index; if (is_min_heap) { if (left < heap->size && heap->data[left] < heap->data[maxmin]) maxmin = left; if (right < heap->size && heap->data[right] < heap->data[maxmin]) maxmin = right; } else { if (left < heap->size && heap->data[left] > heap->data[maxmin]) maxmin = left; if (right < heap->size && heap->data[right] > heap->data[maxmin]) maxmin = right; } if (maxmin != index) { swap(&heap->data[maxmin], &heap->data[index]); down_adjust(heap, maxmin, is_min_heap); } } void up_adjust(Heap* heap, int index, int is_min_heap) { if (index == 0) return; int parent = (index - 1) / 2; if (is_min_heap) { if (heap->data[index] < heap->data[parent]) { swap(&heap->data[index], &heap->data[parent]); up_adjust(heap, parent, is_min_heap); } } else { if (heap->data[index] > heap->data[parent]) { swap(&heap->data[index], &heap->data[parent]); up_adjust(heap, parent, is_min_heap); } } } void insert(Heap* heap, int value, int is_min_heap) { if (heap->size == MAX_HEAP_SIZE) { printf("Heap is full!\n"); return; } heap->data[heap->size] = value; heap->size++; up_adjust(heap, heap->size - 1, is_min_heap); } void remove_heap(Heap* heap, int value, int is_min_heap) { if (heap->size == 0) { printf("Heap is empty!\n"); return; } int i; for (i = 0; i < heap->size; i++) { if (heap->data[i] == value) break; } if (i == heap->size) { printf("Element not found in heap!\n"); return; } heap->data[i] = heap->data[heap->size - 1]; heap->size--; down_adjust(heap, i, is_min_heap); } void print_heap(Heap* heap) { int i; for (i = 0; i < heap->size; i++) printf("%d ", heap->data[i]); printf("\n"); } int main() { Heap* min_heap = create_heap(); Heap* max_heap = create_heap(); insert(min_heap, 5, 1); insert(min_heap, 6, 1); insert(min_heap, 4, 1); insert(min_heap, 2, 1); insert(min_heap, 3, 1); insert(max_heap, 5, 0); insert(max_heap, 6, 0); insert(max_heap, 4, 0); insert(max_heap, 2, 0); insert(max_heap, 3, 0); printf("Min heap: "); print_heap(min_heap); printf("Max heap: "); print_heap(max_heap); remove_heap(min_heap, 4, 1); remove_heap(max_heap, 4, 0); printf("Min heap after removing 4: "); print_heap(min_heap); printf("Max heap after removing 4: "); print_heap(max_heap); return 0; } ``` 这段代码实现了最小最大堆的基本功能,包括创建堆、插入元素、删除元素和打印堆。其中,指定 is_min_heap 参数可以创建最小堆最大堆。注意,在删除元素时,需要先将要删除的元素与堆的最后一个元素交换位置,然后再进行下沉操作,以保证堆的完整性。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值