数据结构学习(七):最大堆和优先队列

版权声明:文章为作者原创,若要转载请获得作者同意。尊重版权,从你我做起! https://blog.csdn.net/qq_37768971/article/details/88565545

一、概念介绍

1.最大堆;

(1)最大堆是一颗完全二叉树、

(2)堆中某个节点的值总是不大于其父节点的值(最大堆)

(3)在数组中表示最大堆
【若数组采用以index=0为根节点】

  • Parent(i)=(i-1)/2
  • Left child=2*i+1
  • Right child=2*i+2

2.优先队列

(1)优先队列是队列中的一种特殊情况;

(2)入队后会自动将优先级最高的元素往前排序;

(3)出队是不按照先进先出,而是优先级高的先出队;

(4)本次数据结构实现以最大堆为基础来实现优先队列。

二、实现的基本功能:

1.最大堆:

isEmpty()

getSize()

void add(E e)

E findMax()

E extractMax()

E replace(E e)

2.优先队列:

getSize;

getFront;

isEmpty;

enqueue;

dequeue;

三、代码及相关注释:

1.最大堆:

(基于数组实现二叉树进而实现最大堆:①数组二叉树

package IMUHERO;

public class MaxHeap <E extends Comparable<E>>{
   public Array<E> data;
   public MaxHeap(int capacity){
        data=new Array<>(capacity);
   }
   public MaxHeap(){
       data=new Array<>();
   }

   //heapify,将一个数组转换成最大堆
    /*Heapify:
    ①寻找最后一个非叶子结点,方法:先找到最后一个叶子结点(length-1),通过这个叶子结点找到它的    父亲节点。
    ②通过sift down方法调整大小位置(父亲节点永远大于子节点);
    ③再使用一层循环逐渐递减直至i=0,完成所有非叶子结点的遍历工作。*/
   public MaxHeap(E [] arr){
        data=new Array<>(arr);
        for (int i=parent(arr.length-1);i>=0;i--){
            siftDown(i);
        }
   }
   public boolean isEmpty(){
       return data.isEmpty();
   }

   public int getSize(){
       return data.getSize();
   }

   private int parent (int index){
       return (index-1)/2;
   }
   private int leftChild(int index){
       return index*2+1;
   }
   private int rightChild(int index){
       return index*2+2;
   }
   /* 2.添加元素
    *①向最后一个位置添加元素(length-1);
    *②对比该元素与父亲节点的大小,若大于父亲节点则交换位置
    *③重复上述操作,只至父亲节点大于子节点*/

   public void add(E e){
       data.addLast(e);
       siftUp(data.getSize()-1);
   }
   private void siftUp(int index){
       while(index>0&&data.get(parent(index)).compareTo(data.get(index))<0){
           data.swap(parent(index),index);
           index=parent(index);
       }
   }

   public E findMax(){
       if (getSize()==0)throw new IllegalArgumentException("There is no element exist");
       return data.get(0);
   }


    /*3.取出最大元素
    (1)小技巧:
    ①将数组下标为0(二叉树根节点)的元素取出
    ②将子节点最后一个替换成根节点,注意删除最后一个子节点
    ③设计使用Sift Down方法,将当前根节点与自己的两个子节点进行比较,选择较大的子节点进行比较。重            复该操作,直至到达最后一层。*/

   public E extractMax(){
       E reMax=findMax();
       data.swap(0,getSize()-1);
       data.removeLast();
       siftDown(0);
       return reMax;
   }
    /*4.siftDown(int index)
    Int j=leftChild(k)
①	判断当前index的左孩子是否大于length(是否有左孩子)
②	判断当前index的左孩子是否有右孩子,如果有则判断左右孩子的大小,若右孩子大于左孩子则j++,否则不变;
③	SWAP 父子节点
④	重复上述判断,直至父亲节点大于等于子节点;*/


   private void siftDown(int index){
       if (index<0||index>getSize())throw new IllegalArgumentException("Index is illegal");
       while(leftChild(index)<getSize()){
           int j=leftChild(index);
           if (j++<getSize()&&data.get(j).compareTo(data.get(j+1))<0)
               j++;
           if (data.get(j).compareTo(data.get(index))<=0) {
               break;       //父亲节点大于等于子节点中最大的值则直接跳出循环
           }
           data.swap(j,index);//如果子节点中有比父亲节点大,则交换并进行下一轮判断
           index=j;
       }
   }

   public E replace(E e){
        E reMax=findMax();
        data.set(0,e);
        siftDown(0);
        return reMax;
   }
}

2.优先队列:(基于最大堆实现)

package IMUHERO;
public interface Queue<E> {

    int getSize();
    boolean isEmpty();
    void enqueue(E e);
    E dequeue();
    E getFront();
}
package IMUHERO;

public class PriorityQueue<E extends Comparable<E>> implements Queue<E>{
    MaxHeap<E> priorityQueue=new MaxHeap<>();

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

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

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

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

    @Override
    public E getFront() {
        return priorityQueue.findMax();
    }
}

注:关于数据结构的所有代码都放在我的Github上,有需要的同学可以自行Fork,如果觉得还不错,可以打个☆Star哦~~~

猜你喜欢

转载自blog.csdn.net/qq_37768971/article/details/88565545