java实现最大堆和优先队列

最大堆

1.堆:是一个可以被看成一棵树的数组对象,满足如下要求:
a:堆中的父亲结点(优先级)总是大于等于孩子结点;
b:必须是一棵完全二叉树(叶子结点的高度差不能超过1,除过树的最后一层,树的其它层必须是满二叉树,按层依次进行排列,组成一颗二叉树)。
2.根据堆的性质可以得出以下结论:

  1. 根结点没有父亲结点;
  2. 除根结点之外的任意结点(i)的父亲结点的索引为:parent = i/2(根结点从1开始)或parent = (i-1)/2(根结点从0开始);
  3. 任意结点(i)的左孩子结点的索引为:leftIndex = i2(根结点从1开始)或leftIndex = i2+1(根结点从0开始);
  4. 任意结点(i)的右孩子结点的索引为:rightIndex = i2+1(根结点从1开始)或rightIndex = i2+2(根结点从0开始)。

3.代码实现

package com.ff.数据结构.myheap;

import java.util.Arrays;

/**
 * 最大堆:
 * 1.是一颗完全二叉树;
 * 2.父亲结点(优先级)总是大于等于孩子结点
 */
public class MaxHeap<T extends Comparable<T>> {
    private T[] data;  //数据容器,保存完全二叉树中结点的内容
    private int size;   //保存树中元素个数

    public MaxHeap(){
        data = (T[])new Comparable[50];
        size = 0;
    }

    //判断树是否为空
    public boolean isEmpty(){
        return this.size == 0;
    }

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

    //获取数据
    public T[] getData(){
        return this.data;
    }

    //向最大堆的这棵树中添加元素
    public void add(T ele){
        data[size] = ele;
        size++;
        //上浮操作
        floatUp(size-1);

        //方法2
        //floatUp2(size-1,ele);

    }

    private void floatUp(int index){
        //获取父亲结点的索引
        int parentIndex = (index-1)/2;
        //进行比较
        while (index > 0 && data[parentIndex].compareTo(data[index])<0){
            swap(data,parentIndex,index);
            index = parentIndex;
            parentIndex = (index - 1)/2;
        }
    }

    private void floatUp2(int index,T ele){
        //获取父亲结点
        int parentIndex = (index - 1)/2;
        while (index>0 && data[parentIndex].compareTo(ele)<0){
            data[index] = data[parentIndex];
            index = parentIndex;
            parentIndex = (index - 1)/2;
        }
        data[index] = ele;
    }

    //取出优先级最高的元素
    public T removeEle() throws IllegalAccessException {
        if(isEmpty()){
            throw new IllegalAccessException("the maxHeap is empty!");
        }
        T ele = data[0];
        //下沉操作
        swim();
        return ele;
    }

    private void swim(){
        data[0] = data[size-1];
        size--;
        //当前结点
        int currentIndex = 0;
        int leftIndex = currentIndex * 2 + 1;
        int changeIndex = leftIndex;
        //找到左右子树优先权最高的结点
        while (leftIndex<size){
            if(leftIndex+1<size && data[leftIndex+1].compareTo(data[leftIndex])>0){
                changeIndex+=1;
            }
            if(data[currentIndex].compareTo(data[changeIndex])<0){
                //交换操作
                swap(data,currentIndex,changeIndex);
                currentIndex = changeIndex;
                leftIndex = currentIndex*2+1;
                changeIndex = leftIndex;
            }else {
                break;
            }
        }
    }

    //替换优先级最高的元素
    public void replace(T newValue) throws IllegalAccessException {
        if(isEmpty()){
            throw new IllegalAccessException("the maxHeap is empty!");
        }
        swim(newValue);


    }

    private void swim(T newValue){
        data[0] = newValue;
        int currentIndex = 0;
        int leftIndex = currentIndex*2 + 1;
        int changeIndex = leftIndex;
        while (leftIndex<size){
            if(leftIndex+1<size && data[leftIndex+1].compareTo(data[leftIndex])>0){
                changeIndex += 1;
            }
            if(data[currentIndex].compareTo(data[changeIndex])<0){
                swap(data,changeIndex,currentIndex);
                currentIndex = changeIndex;
                leftIndex = currentIndex*2 + 1;
                changeIndex = leftIndex;
            }else {
                break;
            }
        }
    }

    //将任意数组整理成堆
    public void heapify(T[] arr) throws IllegalAccessException {
        if(arr == null || arr.length == 0){
            throw new IllegalAccessException("the array is empty!");
        }
        //从最后一个结点的父结点开始做下沉操作
        int adjustIndex = (arr.length - 1 - 1)/2;
        for(;adjustIndex>=0;adjustIndex--){
            swim(arr,adjustIndex,arr.length);
        }
    }

    private void swim(T[] arr,int index,int lenght){
        int currentIndex = index;
        int leftIndex = currentIndex*2 + 1;
        int changeIndex = leftIndex;
        while (leftIndex<lenght){
            if(leftIndex+1<lenght && arr[leftIndex+1].compareTo(arr[leftIndex])>0){
                changeIndex += 1;
            }
            if(arr[changeIndex].compareTo(arr[currentIndex])>0){
                swap(arr,changeIndex,currentIndex);
                currentIndex = changeIndex;
                leftIndex = currentIndex*2 + 1;
                changeIndex = leftIndex;
            }
        }
    }
    //辅助方法(交换操作)
    private void swap(T[] arr,int parentIndex,int index){
        T temp = arr[parentIndex];
        arr[parentIndex] = arr[index];
        arr[index] = temp;
        /*arr[index] = arr[index] - arr[parentIndex];
        arr[parentIndex] = arr[parentIndex] + arr[index];
        arr[index] = arr[parentIndex] - arr[index];*/
    }

    @Override
    public String toString(){
        StringBuffer sb = new StringBuffer();

        for(int i=0;i<size;i++){
            sb.append(data[i] + ",");
        }
        return sb.substring(0,sb.lastIndexOf(",")).toString();
    }

    public static void main(String[] args) throws IllegalAccessException {
        MaxHeap<Integer> maxHeap = new MaxHeap<>();
        Integer[] arr = {1,34,6,23,56,66,43};
        for(int i=0;i<arr.length;i++){
            maxHeap.add(arr[i]);
        }
        System.out.println(maxHeap);
        System.out.println(maxHeap.getSize());
        maxHeap.removeEle();
        System.out.println(maxHeap);
        System.out.println(maxHeap.getSize());
        maxHeap.replace(33);
        System.out.println(maxHeap);
        System.out.println(maxHeap.getSize());
        Integer[] arr1 = {2,4,23,76,32,44,45};
        MaxHeap<Integer> maxHeap1 = new MaxHeap<>();
        maxHeap1.heapify(arr1);
        System.out.println(Arrays.toString(arr1));
        //System.out.println(maxHeap1.getSize());
    }
}

优先队列

1.优先队列:出队顺序和入队顺序无关,和优先级有关,当访问元素时,优先级最高的会被删除,可以使用堆这种数据结构作为优先队列的底层结构。
2.代码实现
利用堆作为数据容器

package com.ff.数据结构.myheap;

import com.ff.数据结构.stackandqueue.Queue;

public class priorityQueue<T extends Comparable<T>> implements Queue<T> {
    private MaxHeap<T> maxHeap;
    @Override
    public void enqueue(T ele) throws IllegalAccessException {
        maxHeap.add(ele);
    }

    @Override
    public T dequeue() throws IllegalAccessException {
        return maxHeap.removeEle();
    }

    @Override
    public T getFront() throws IllegalAccessException {
        return maxHeap.getData()[0];
    }

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

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

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值