算法与数据结构(10)—— 二叉堆(堆排序、Heapify)

一. 堆结构

1.优先队列

  • 普通队列:先进先出,后进后出。
  • 优先队列:优先级高的先出来,与时间无关、

应用:优先队列在OS的使用,CPU调度时间片,每次优先选择优先级最高的任务执行,注意是动态的~;不仅仅适用于OS,还有在请求某个网页,服务器按需要返回,回应的一般是按照优先队列决定的~

处理问题:之前的排序算法,N个元素选前M个元素,时间复杂度O(nlogn),使用优先队列时,可将时间复杂度降低为O(NlogM)

主要操作:入队,出队(取优先级最高的元素)

可以采取的数据结构数组(普通,顺序),堆(平均而言要好)


2. 二叉堆(Binary Heap)的基本实现

堆的实现通过构造二叉堆,具有以下性质:

  • 任意节点小于(或大于)它的所有后裔,最小元(或最大元)在堆的根上(堆序性)。

  • 堆总是一棵完全树。即除了最底层,其他层的节点都被元素填满,且最底层尽可能地从左到右填入。


public class MaxHeap<Item> {

    private Item[] data;
    private int count;

    // 构造函数, 构造一个空堆, 可容纳capacity个元素
    public MaxHeap(int capacity){
        data = (Item[])new Object[capacity+1];
        count = 0;
    }

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

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

接下来就是往里面添加插入,拿出元素,即shift up, shift down操作

   //在最大堆中插入一个新的元素 item
    public void insert(Item item){

        assert count + 1 <= capacity;
        data[count + 1] = item;
        count ++;
        shiftUp(count);
    }
    private void shiftUp(int k){

        while(k > 1 && data[k/2].compareTo(data[k]) < 0){
            swap(k, k/2);
            k /= 2;
        }
    }
    private void swap(int i, int j){
        Item t = data[i];
        data[i] = data[j];
        data[j] = t;
    }


    //从最大堆中取出堆顶元素,即堆中所存储的最大数据
    public Item extractMax(){
        assert count > 0;
        Item res = data[1];
        swap(1, count);
        count --;
        shiftDown(1);

        return res;
    }
    private void shiftDown(int k){

        while( 2*k <= count){
            int j = 2*k;
            if(j+1 <= count && data[j+1].compareTo(data[j]) > 0) j++;
            if(data[k].compareTo(data[j]) >= 0) break;
            swap(k, j);
            k = j;     // k就下来了,j是k的子节点
        }
    }

3. 堆排序:

堆排序:将一个数组中的值一个一个的插入堆中,然后再一个一个的取出来(取出来也只能是最大值)

Heapify:之前的是一个一个的插入,选择将整个数组传入堆的构造方法,这样只需要从最后一个有孩子的结点开始算起~

    //构造函数,通过给定一个数组创建一个最大堆,构建堆的过程,时间复杂度为O(n)
    public MaxHeap(Item[] arr){
        int n = arr.length;

        data = (Item[])new Comparable[n+1];
        capacity = n;

        for(int i = 0; i < n; i ++){
            data[i+1] = arr[i];
        }
        count = n;

        for(int i = count/2; i >= 1; i --){
            shiftDown(i);
        }

    }


猜你喜欢

转载自blog.csdn.net/jae_wang/article/details/80579743
今日推荐