【Java】实现堆,并使用堆模拟优先级队列

学习目标:

目标:熟练运用Java所学知识


学习内容:

本文内容:实现堆,并使用堆模拟优先级队列


模拟思路:

模拟优先级队列首先要明确都需要实现什么功能,本篇文章实现了一下功能

  1. 首先需要在类中创建两个参数
    private int[] arr = new int[100];//用于存储插入的数据
    private int size = 0;//记录优先级队列数组中有效元素个数
  1. 重写toStirng方法,用于打印优先级队列对象
    @Override
    public String toString() {
        //将数组中的有效元素拷贝到新数组并返回
        int[] newArr=Arrays.copyOf(arr,size);
        return Arrays.toString(newArr);
    }

  1. 使用数组作为参数创建优先级队列,也就是说将数组通过小顶堆的方式进行排序,这里就需要使用到向下调整的方法
 //向下调整
    public  void shiftDown(int[] arr, int index, int size) {
        int parent = index;//需要调整的位置
        int child = 2 * parent + 1;//chile标记parent的左孩子节点
        while (child < size) {
            if (child + 1 < size && arr[child] > arr[child + 1]) {
                //判断parent左右孩子的大小关系,让child标记较大的孩子节点
                child = child + 1;
            }
            //判断parent和child位置的元素的大小关系,
            //如果arr[child] < arr[parent],则交换位置
            if (arr[child] < arr[parent]) {
                int tmp = arr[child];
                arr[child] = arr[parent];
                arr[parent] = tmp;
            } else {
                //否则arr[parent]就已经找到了合适的位置结束循环
                break;
            }
            parent = child;//更新parent标记的位置
            child = 2 * parent + 1;//更新child标记的位置,继续下次循环
        }
    }
    //使用数组创建堆(向下调整)
    public  void creatHeap(int arr[]) {
        for (int i = (arr.length - 1 - 1) / 2; i >= 0; i--) {
            shiftDown(arr, i, arr.length);
        }
        this.arr=arr;
        size=arr.length;
    }
  1. 向优先级队列中插入元素
 //向上调整
   public  void shiftUp(int[] arr, int size, int index) {
       int child = index;//让child标记要调整元素的位置
       int parent = (child - 1) / 2;//child位置的父亲位置
       while (child > 0) {
           //如果arr[child] < arr[parent],则交换位置
           if (arr[child] < arr[parent]) {
               int temp = arr[child];
               arr[child] = arr[parent];
               arr[parent] = temp;
           } else {
               //否则就找到的index位置元素该在的位置
               break;
           }
           child = parent;//更新child位置,进行下次循环
           parent = (child - 1) / 2;//更新parent位置,进行下次循环
       }
   }

   //向堆中插入元素
   public  void offer(int val) {
       if (size >= arr.length) {
           return;
       }
       arr[size++] = val;
       shiftUp(arr, size, size - 1);
   }

  1. 获取优先级队列中优先级最高的数
    //获取堆顶元素
    public  Integer peek() {
        if (size == 0) {
            return null;
        }
        int res = arr[0];
        return res;
    }
  1. 删除优先级最高的元素
  //删除堆顶元素
    public  Integer poll() {
        if (size == 0) {
            return null;
        }
        int res = arr[0];
        //交换操作
        int temp = arr[0];
        arr[0] = arr[size - 1];
        arr[size - 1] = temp;
        size--;//堆的有效元素个数减一就实现了删除元素
        shiftDown(arr, 0, size);//对堆顶元素进行向下调整
        return res;
    }

代码汇总:

public class MyPriorityQueue {
      private int[] arr = new int[100];//用于存储插入的数据
    private int size = 0;//记录数组有效元素个数

    //重写toString方法
    @Override
    public String toString() {
        //将数组中的有效元素拷贝到新数组并返回
        int[] newArr=Arrays.copyOf(arr,size);
        return Arrays.toString(newArr);
    }


    //向下调整
    public  void shiftDown(int[] arr, int index, int size) {
        int parent = index;//需要调整的位置
        int child = 2 * parent + 1;//chile标记parent的左孩子节点
        while (child < size) {
            if (child + 1 < size && arr[child] > arr[child + 1]) {
                //判断parent左右孩子的大小关系,让child标记较小的孩子节点
                child = child + 1;
            }
            //判断parent和child位置的元素的大小关系,
            //如果arr[child] < arr[parent],则交换位置
            if (arr[child] < arr[parent]) {
                int tmp = arr[child];
                arr[child] = arr[parent];
                arr[parent] = tmp;
            } else {
                //否则arr[parent]就已经找到了合适的位置结束循环
                break;
            }
            parent = child;//更新parent标记的位置
            child = 2 * parent + 1;//更新child标记的位置,继续下次循环
        }
    }

    //向上调整
    public  void shiftUp(int[] arr, int size, int index) {
        int child = index;//让child标记要调整元素的位置
        int parent = (child - 1) / 2;//child位置的父亲位置
        while (child > 0) {
            //如果arr[child] < arr[parent],则交换位置
            if (arr[child] < arr[parent]) {
                int temp = arr[child];
                arr[child] = arr[parent];
                arr[parent] = temp;
            } else {
                //否则就找到的index位置元素该在的位置
                break;
            }
            child = parent;//更新child位置,进行下次循环
            parent = (child - 1) / 2;//更新parent位置,进行下次循环
        }
    }

    //使用数组创建堆(向下调整)
    public  void creatHeap(int newArr[]) {
        for(int i:newArr){
            arr[size++]=i;
        }
        for (int i = (size - 1 - 1) / 2; i >= 0; i--) {
            shiftDown(arr, i, size);
        }
    }

    //使用数组创建堆(向上调整)
    public  void creatHeap2(int arr[]) {
        for (int x : arr) {
            offer(x);
        }
    }

    //向堆中插入元素
    public  void offer(int val) {
        if (size >= arr.length) {
            return;
        }
        arr[size++] = val;
        shiftUp(arr, size, size - 1);
    }

    //获取堆顶元素
    public  Integer peek() {
        if (size == 0) {
            return null;
        }
        int res = arr[0];
        return res;
    }

    //删除堆顶元素
    public  Integer poll() {
        if (size == 0) {
            return null;
        }
        int res = arr[0];
        //交换操作
        int temp = arr[0];
        arr[0] = arr[size - 1];
        arr[size - 1] = temp;
        size--;//堆的有效元素个数减一就实现了删除元素
        shiftDown(arr, 0, size);//对堆顶元素进行向下调整
        return res;
    }

}

测试用例

    public static void main(String[] args) {
        MyPriorityQueue m=new MyPriorityQueue();
        m.offer(6);//插入元素
        m.offer(5);//插入元素
        m.offer(4);//插入元素
        m.offer(3);//插入元素

        int[] arr={9,2,7};
        m.creatHeap(arr);//将数组插入到优先级队列中

        System.out.println(m.peek());//打印优先级最高的元素
        m.poll();//删除优先级最高的元素
        System.out.println(m.peek());//运行结果 3
        m.poll();//删除优先级最高的元素
        System.out.println(m.peek());//运行结果 4

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值