贪心算法+Java实现C的函数指针

来源:互联网 发布:js刷新div 编辑:程序博客网 时间:2024/05/01 20:21

先囧一下,其实本来没有这篇的。
最近在读算法的相关书籍,正好读到贪心算法,大家知道算法的书籍大多是通过C或C++来提供源码的,贪心算法经常会涉及到多个计算结果的对比然后取最优解,C++的处理方式一般都是函数指针,提供一个类似函数指针的数组,然后遍历循环每个函数获得result的结果集。然而java是没有指针的,当然更没有函数指针这一说,那遇到这种情况我们代码要怎么写呢。
百度喵了一眼,看到两个字,接口。
没错,就是接口。接口 + 多态,抽象来看不就是一个方法,多个实现嘛。不过区别在于函数指针可以随便指定函数,而接口相当于一个规范,不满足这个规范的方法我们是无法通过接口去调用的。不过,既然现在需求是循环一系列函数获取某个值并进行比较,那这些函数一定是遵循一个规范的,所以我们用接口一定可以搞定。
顺便简单介绍下贪心算法:
贪心算法(又称贪婪算法)是指,在对问题求解时,总是做出在当前看来是最好的选择。也就是说,不从整体最优上加以考虑,他所做出的是在某种意义上的局部最优解。
贪心算法不是对所有问题都能得到整体最优解,关键是贪心策略的选择,选择的贪心策略必须具备无后效性,即某个状态以前的过程不会影响以后的状态,只与当前状态有关。
贪心算法的经典问题就是0-1背包问题,N个物品,1个背包,每个物品的重量为w1到wN,价值为p1到pN,背包能承载的最大重量为C,求解最优的装法。当然前提是物品只有装和不装两个选择,不存在装多个的问题,所以叫01背包问题。
好了,铺垫完了,上代码:

package com.amuro.greedy;public class Goods{    public int weight;    public int price;}

首先定义我们的物品类,封装重量和价值。下面定义接口:

package com.amuro.greedy.algorithm;import java.util.List;import com.amuro.greedy.Goods;public interface IGreedy{    public static final int CAPACITY = 150;    public int getResult(List<Goods> goodsList);}

很简单,就一个getResult方法来获取算法的结果,而CAPACITY为设定的背包的最大重量。然后来看三个贪心的实现,分别是:每次取最贵的,每次取最轻的(让物品数量最多),每次取价格密度最高的(price / weight):

package com.amuro.greedy.algorithm;import java.util.ArrayList;import java.util.List;import com.amuro.greedy.Goods;/** * 每次优先选最贵的 * @author Amuro * */public class Greedy1 implements IGreedy{    @Override    public int getResult(List<Goods> goodsList)    {        if(goodsList == null || goodsList.size() == 0)        {            return -1;        }        @SuppressWarnings("unchecked")        List<Goods> tempList = (List<Goods>) ((ArrayList<Goods>)goodsList).clone();        int result = 0;        int currentWeight = 0;        while(true)        {            Goods maxPriceGoods = selectTheMostExpensiveGoods(tempList);            currentWeight += maxPriceGoods.weight;            if(currentWeight > 150)            {                break;            }            result += maxPriceGoods.price;            tempList.remove(maxPriceGoods);        }        return result;    }    private Goods selectTheMostExpensiveGoods(List<Goods> tempList)    {        Goods maxPriceGoods = tempList.get(0);        for(int i = 1; i < tempList.size(); i++)        {            Goods goods = tempList.get(i);            if(goods.price > maxPriceGoods.price)            {                maxPriceGoods = goods;            }        }        return maxPriceGoods;    }}
package com.amuro.greedy.algorithm;import java.util.ArrayList;import java.util.List;import com.amuro.greedy.Goods;/** * 每次选最轻的 * @author Amuro * */public class Greedy2 implements IGreedy{    @Override    public int getResult(List<Goods> goodsList)    {        if(goodsList == null || goodsList.size() == 0)        {            return -1;        }        @SuppressWarnings("unchecked")        List<Goods> tempList = (List<Goods>) ((ArrayList<Goods>)goodsList).clone();        int result = 0;        int currentWeight = 0;        while(true)        {            Goods lightestGoods = selectedTheLightestGoods(tempList);            currentWeight += lightestGoods.weight;            if(currentWeight > 150)            {                break;            }            result += lightestGoods.price;            tempList.remove(lightestGoods);        }        return result;    }    private Goods selectedTheLightestGoods(List<Goods> tempList)    {        Goods lightestGoods = tempList.get(0);        for(int i = 1; i < tempList.size(); i++)        {            Goods goods = tempList.get(i);            if(goods.weight < lightestGoods.weight)            {                lightestGoods = goods;            }        }        return lightestGoods;    }}
package com.amuro.greedy.algorithm;import java.util.ArrayList;import java.util.List;import com.amuro.greedy.Goods;/** * 每次选价值密度最高的 * @author Amuro * */public class Greedy3 implements IGreedy{    @Override    public int getResult(List<Goods> goodsList)    {        if(goodsList == null || goodsList.size() == 0)        {            return -1;        }        @SuppressWarnings("unchecked")        List<Goods> tempList = (List<Goods>) ((ArrayList<Goods>)goodsList).clone();        int result = 0;        int currentWeight = 0;        while(true)        {            Goods mostDensityGoods = selectedMostDensityGoods(tempList);            currentWeight += mostDensityGoods.weight;            if(currentWeight > 150)            {                break;            }            result += mostDensityGoods.price;            tempList.remove(mostDensityGoods);        }        return result;    }    private Goods selectedMostDensityGoods(List<Goods> tempList)    {        Goods mostDensityGoods = tempList.get(0);        for(int i = 1; i < tempList.size(); i++)        {            Goods goods = tempList.get(i);            float mostDensity = mostDensityGoods.price / mostDensityGoods.weight;            float currentDensity = goods.price / goods.weight;            if(currentDensity > mostDensity)            {                mostDensityGoods = goods;            }        }        return mostDensityGoods;    }}

代码很好理解,就不多说了,注意拿到传进来的list记得要clone,不然做了remove操作后,原来的list也被你改了。这里发现个bug,就是循环退出的条件不够,如果所有物品重量加起来都没有超过150程序就要死循环了,嘛,如果这样这个最优解也没有意义了,各位可自行修改,本来重点也不是这个。
好,当我们涉及多个算法的时候,脑子里的第一反应是什么,没错,策略模式,我们需要封装一个类供外部调用,隐藏算法的细节和调用方式。来看GreedyManager类:

package com.amuro.greedy;import java.util.List;import com.amuro.greedy.algorithm.IGreedy;public class GreedyManager{    private List<Goods> goodsList;    private String[] algorithems = {            "com.amuro.greedy.algorithm.Greedy1",             "com.amuro.greedy.algorithm.Greedy2",            "com.amuro.greedy.algorithm.Greedy3"};    public GreedyManager(List<Goods> goodsList)    {        this.goodsList = goodsList;    }    public int doAlgorithm() throws InstantiationException, IllegalAccessException, ClassNotFoundException    {        int result = getClass(algorithems[0]).getResult(goodsList);        for(int i = 1;i < algorithems.length; i++)        {            int temp = getClass(algorithems[i]).getResult(goodsList);            if(temp > result)            {                result = temp;            }        }        return result;    }    private IGreedy getClass(String className) throws InstantiationException, IllegalAccessException, ClassNotFoundException    {        return ((IGreedy)Class.forName(className).newInstance());    }}

OK,这篇的重点基本都在这个类了。C++的函数指针数组我们没法实现,但别忘了我们有反射,所以我们可以配置一个类名的数组供循环来调用。然后通过循环,得到每一种贪心计算结果的result,再取出最大的结果给外部调用者。以后再有新的贪心计算规则时,只要增加一个IGreedy的子类,并在数组中增加一个String就可以啦~ 传说中的对修改关闭,对扩展开放。
最后看一下客户端调用:

package com.amuro.greedy;import java.util.ArrayList;import java.util.List;public class Client{    public static void main(String[] args)    {        Client clt = new Client();        clt.doAlgorithm();    }    private List<Goods> goodsList;    private GreedyManager greedyManager;    public Client()    {        init();    }    private int[] weights = {35, 30, 60, 50, 40, 10, 25};    private int[] prices = {10, 40, 30, 50, 35, 40, 30};    private void init()    {        goodsList = new ArrayList<>();        for(int i = 0;i < weights.length;i++)        {            Goods goods = new Goods();            goods.weight = weights[i];            goods.price = prices[i];            goodsList.add(goods);        }        greedyManager = new GreedyManager(goodsList);    }    public void doAlgorithm()    {        try        {            System.out.println("Result->" + greedyManager.doAlgorithm());        }        catch (InstantiationException e)        {            e.printStackTrace();        }        catch (IllegalAccessException e)        {            e.printStackTrace();        }        catch (ClassNotFoundException e)        {            e.printStackTrace();        }    }}

看一下输出结果:Result->170。
大家有兴趣可以自己算一下,第三种贪心算法就是最优解170~
就酱~

0 0
原创粉丝点击
热门问题 老师的惩罚 人脸识别 我在镇武司摸鱼那些年 重生之率土为王 我在大康的咸鱼生活 盘龙之生命进化 天生仙种 凡人之先天五行 春回大明朝 姑娘不必设防,我是瞎子 孕吐吐到胃出血怎么办 孩子不会写2怎么办 口渴了怎么办大班教案 小班健康跌倒了怎么办 刷油漆有纹路怎么办 纯白门会发黄怎么办 发现小孩子偷钱怎么办 青春期孩子偷钱怎么办 孩子偷钱屡教不改怎么办 孩子经常偷钱怎么办 小孩子总是偷钱怎么办 小孩喜欢偷钱怎么办 小孩老是偷钱怎么办 如果孩子偷钱怎么办 小孩在家偷钱怎么办 买了西晒房怎么办 乳胶漆有打磨痕迹怎么办 墙上乳胶漆用水擦完太亮了怎么办 外墙腻子不好打磨怎么办 腻子打磨的灰尘怎么办 家里的壁纸脏了怎么办 家装用冷风管冬天取暖怎么办? 房子装修冷色系怎么办 高血压突然变低血压怎么办 玩单机游戏卡顿怎么办 老人血压太低怎么办 老年人血压太低怎么办 觉总是不够睡怎么办 老年人气不够用怎么办 卧室晒不到太阳怎么办 农村房子墙角受潮怎么办 房间里面有虫子怎么办 墙壁发霉生虫子怎么办 墙壁发霉有虫子怎么办 墙面发霉有虫子怎么办 白漆墙面脏了怎么办 房间贴完墙墙面发霉怎么办? 家里的墙壁发霉怎么办 黑豆生虫了怎么办 家具有小虫子怎么办 店铺对面有镜子怎么办