总结:堆结构

堆结构非常重要。因此特别记录一下有关堆结构的知识点。
1.最重要的堆排序问题:
java参考代码如下:

package chapter2;

public class P79_heapSort {

    public static void heapSort(int[] arr) {
        if (arr == null || arr.length < 2) {
            return;
        }
        for (int i = 0; i < arr.length; i++) {
            heapInsert(arr, i);//maxHeap
        }
        int size = arr.length;
        swap(arr, 0, --size);
        while (size > 0) {
            heapify(arr, 0, size);
            swap(arr, 0, --size);//从末尾开始,每次搞定一个数
        }
    }

    public static void heapInsert(int[] arr, int index) {//maxHeap
        while (arr[index] > arr[(index - 1) / 2]) {
            swap(arr, index, (index - 1) / 2);
            index = (index - 1) / 2;
        }
    }

    public static void heapify(int[] arr, int index, int size) {//size-->heapSize
        int left = index * 2 + 1;
        while (left < size) {
            int largest = left + 1 < size && arr[left + 1] > arr[left] ? left + 1 : left;//left+1--->right
            largest = arr[largest] > arr[index] ? largest : index;
            if (largest == index) {
                break;
            }
            swap(arr, largest, index);
            index = largest;
            left = index * 2 + 1;
        }
    }

    public static void swap(int[] arr,int i,int j){
        arr[i]=arr[i]^arr[j];
        arr[j]=arr[i]^arr[j];
        arr[i]=arr[i]^arr[j];
    }

    public static void main(String[] args) {
        int[] arr={1,3,5,7,9,2,4,6,8};
        heapSort(arr);
        for(int num:arr){
            System.out.print(num+" ");
        }
    }
}

2.哈夫曼问题中的小根堆。
一块金条切成两半, 是需要花费和长度数值一样的铜板的。 比如
长度为20的 金条, 不管切成长度多大的两半, 都要花费20个铜
板。 一群人想整分整块金 条, 怎么分最省铜板?
例如,给定数组{10,20,30}, 代表一共三个人, 整块金条长度为
10+20+30=60. 金条要分成10,20,30三个部分。 如果, 先把长
度60的金条分成10和50, 花费60 再把长度50的金条分成20和30,
花费50 一共花费110铜板。
但是如果, 先把长度60的金条分成30和30, 花费60 再把长度30
金条分成10和20, 花费30 一共花费90铜板。
输入一个数组, 返回分割的最小代价。

思路:
将输入的数组全部放到小根堆里面,每次取小的两个,所得的和再放入堆中,途中记录累加和,知道堆中只剩下一个。

java参考代码如下:

package zuoshen1;

import java.util.Comparator;
import java.util.PriorityQueue;

public class HuffmanTree {
    public static int lessMoney(int[] arr){
        if(arr==null||arr.length<1)
            throw new RuntimeException("arr is null!");
        PriorityQueue<Integer> pq=new PriorityQueue<>(new MinheapComparator());//可以默认,默认为小根堆
        for(int i=0;i<arr.length;i++){
            pq.add(arr[i]);
        }
        int sum=0,cur=0;
        while (pq.size()>1){//==1 break
            cur=pq.poll()+pq.poll();
            sum+=cur;
            pq.add(cur);
        }
        return sum;
    }
    public static class MinheapComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o1 - o2; // < 0  o1 < o2  负数
        }

    }

    public static class MaxheapComparator implements Comparator<Integer> {

        @Override
        public int compare(Integer o1, Integer o2) {
            return o2 - o1; // <   o2 < o1
        }
    }

    public static void main(String[] args) {
        System.out.println(lessMoney(new int[]{10,20,30}));
    }
}

3.输入: 参数1, 正数数组costs 参数2, 正数数组profits 参数3,
正数k 参数4, 正数m
costs[i]表示i号项目的花费 profits[i]表示i号项目在扣除花
费之后还能挣到的钱(利润) k表示你不能并行、 只能串行的最多
做k个项目 m表示你初始的资金
说明: 你每做完一个项目, 马上获得的收益, 可以支持你去做下
一个 项目。
输出: 你最后获得的最大钱数。

思路:
投资,你有当前资金W,你一共可以投资K次,且每次只能投一个。我们用两个堆来解决这个问题,小根堆根据项目的cost来建立,大根堆根据每个项目的profit来建立。我们将小根堆中cost小于当前W的项目放到大根堆中,再根据大根堆的构建原理,从中拿出最大收益的进行投资,直到大根堆为空,或者投资K个截止。
java参考代码如下:

package zuoshen1;

import java.util.Comparator;
import java.util.PriorityQueue;

public class FindMaximizedCapital {
    public static class Node{
        int c;
        int p;
        public Node(int c,int p){
            this.c=c;
            this.p=p;
        }
    }
    public static class MinComparator implements Comparator<Node>{
        @Override
        public int compare(Node o1,Node o2){
            return o1.c-o2.c;//min cost
        }
    }
    public static class MaxComparator implements Comparator<Node>{
        @Override
        public int compare(Node o1,Node o2){
            return o2.p-o1.p;//max profit
        }
    }
    public static int findMaximizedCapital(int k,int w,int[] cost,int[] profit){
        if(k<0||w<0||cost==null||profit==null||cost.length!=profit.length)
            throw new RuntimeException("run exception!");
        Node[] nodes=new Node[cost.length];
        PriorityQueue<Node> minQ=new PriorityQueue<>(new MinComparator());
        PriorityQueue<Node> maxQ=new PriorityQueue<>(new MaxComparator());
        for(int i=0;i<cost.length;i++){
            nodes[i]=new Node(cost[i],profit[i]);
        }
        for(int i=0;i<cost.length;i++){
            minQ.add(nodes[i]);
        }
        for(int i=0;i<k;i++){
            while (!minQ.isEmpty()&&minQ.peek().c<=w){//w>=cost[i]//w 是当前的资金,一直在增
                maxQ.add(minQ.poll());
            }
            if(maxQ.isEmpty()){
                return w;
            }
            //else maxQ is not empty!
            w+=maxQ.poll().p;
        }
        return w;
    }

    public static void main(String[] args) {
        int[] cost={5,6,7,8,9,20};
        int[] profit={1,2,3,5,6,10};
        int w=10;
        int k1=4;
        int k2=6;
        System.out.println(findMaximizedCapital(k1,w,cost,profit));
        System.out.println(findMaximizedCapital(k2,w,cost,profit));
    }
}

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值