算法导论-堆排序+优先队列

定义

二叉堆是一个数组,可以被看做一个近似的完全二叉树。
性质:

  • 含有n个元素的堆的高度是lgn。
  • 在最大堆中,最大元素该子树的根上;在最小堆中,最小元素在该子树的根上。

建堆,向下调整堆,向上调整堆

  1. 建堆
    可以使用自底向上的方法利用过程maxHeapify(向下调整堆)把数组A[1-n]转换为堆。
    伪代码
    这里写图片描述
  2. 向下调整堆maxHeapify
    伪代码
    这里写图片描述
    算法描述
    这里写图片描述
    这里写图片描述
    3.向上调整堆
    代码
//向上调整堆
    private void adjustUp(int a[],int index){
        int parent = index/2;
        while(index>0 && a[parent] < a[index]) {
            int t = a[parent];
            a[parent] = a[index];
            a[index] = t;
            index = parent;
            parent = parent/2;
        }
    }

向上调整的操作过程中,当前元素会不断地与其父节点进行比较,如果当前元素的关键字较大,则当前元素与其父节点进行交换。这一过程会不断地重复,直到当前元素的关键字小于其父节点时终止,因为此时已经重新符合了最大堆的性质。

堆排序

这里写图片描述
代码

public class MaxHeap {

    //堆排序
    public static void heapSort(int[] a) {
        buildMaxheap(a,a.length);
        for(int i = a.length-1;i>=1;i--) {
            int t = a[i]; a[i] = a[0]; a[0] = t;
            maxHeapify(a,0,i);
        }
    }

    //建堆
    private static void buildMaxheap(int[] a,int heapSize) {
        for (int i = heapSize; i >= 0; i--) {
            maxHeapify(a,i,heapSize);
        }
    }

    //向下调整堆,选择左右子树中比当前节点大的值进行交换,并继续向下递归,直至到达树底或子树已满足堆的性质
    private static void maxHeapify(int[] a,int index,int heapSize) {
        int l = index*2;
        int r = l+1;
        int largest = index;
        if(l<heapSize && a[l]>a[largest])
            largest = l;
        if(r<heapSize && a[r]>a[largest])
            largest = r;
        if(index != largest) {
            int t = a[index]; a[index] = a[largest]; a[largest]=t;
            maxHeapify(a,largest,heapSize);
        }
    }

    public static void main(String[] args) {
        int[] a = {4,1,3,2,16,9,10,14,8,7};
        MaxHeap.heapSort(a);
        for(int i=0;i<a.length;i++)
            System.out.println(a[i]);

    }

}

优先队列

这里写图片描述

public class PriorityQueue {
    private int MAX = 100; 
    private int[] data = new int[MAX];
    private int size = 0;

    //把元素插入队列中
    public boolean insert(int x) {
        if(size == MAX)
            return false;//队列已满
        data[size] =  x;
        adjustUp(data,size);
        size++;
        return true;
    }

    //返回最大键字的元素
    public int maximum() {
        if(size == 0)
            return -1;
        return data[0];
    }

    //去掉并返回最大键值
    public int extractMax() {
        if(size == 0)
            return -1;
        int max = data[0];
        data[0] = data[size-1];
        size = size - 1;
        adjustDown(data,0,size);
        return max;
    }

    //将第index位的关键字增加到k
    public void increaseKey(int index,int k){
        if(index >=0 && index<size && data[index]<k) {
            data[index] = k;
            adjustUp(data,index);
        }
    }

    //向上调整堆
    private void adjustUp(int a[],int index){
        int parent = index/2;
        while(index>0 && a[parent] < a[index]) {
            int t = a[parent];
            a[parent] = a[index];
            a[index] = t;
            index = parent;
            parent = parent/2;
        }
    }

    //向下调整堆
    private void adjustDown(int[] a,int index,int heapSize) {
        int l = index*2;
        int r = l+1;
        int large = index;
        if(l<heapSize && a[large] < a[l])
            large = l;
        if(r<heapSize && a[large] < a[r])
            large = r;
        if(index != large) {
            int t = a[index]; a[index] = a[large]; a[large] = t;
            adjustDown(a,large,heapSize);
        }
    }
}
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值