权重随机的实现

欢迎关注Github:https://github.com/teaey/

权重随机在项目中经常用到,所以我把它抽象到一个工具类中。

一般实现随机权重有两种方式:

1. 使用一个数组存放权重对应的实际目标,比如A的权重是2,B的权重是3,那么数组长度为5, 数组前两个存放A,后三个存放B。

然后随机一个[0-数据长度)的数字,直接取数组对应下标的值就可以了。

优点:数据结构简单,算法高效,实现简单

缺点:当权重值比较大同时数据又比较多的时候,会浪费内存

2. 使用区间算法,从前到后依次叠加权重,然后随机一个[1-权重和]的数字,再用随机的权重依次减去每个元素的权重,当第一个小于等于0的元素就是我们找元素

这里实现可以借用Arrays的binarySearch方法。

源码可参考Github:源码

贴一下代码:

WeightMeta.java
/**
 * 建议使用RandomUtil类创建RandomMeta对象
 * @author wxf on 14-5-5.
 */
public class WeightMeta<T> {
    private final Random ran = new Random();
    private final T[] nodes;
    private final int[] weights;
    private final int maxW;

    public WeightMeta(T[] nodes, int[] weights) {
        this.nodes = nodes;
        this.weights = weights;
        this.maxW = weights[weights.length - 1];
    }

    /**
     * 该方法返回权重随机对象
     * @return
     */
    public T random() {
        int index = Arrays.binarySearch(weights, ran.nextInt(maxW) + 1);
        if (index < 0) {
            index = -1 - index;
        }
        return nodes[index];
    }

    public T random(int ranInt) {
        if (ranInt > maxW) {
            ranInt = maxW;
        } else if(ranInt < 0){
            ranInt = 1;
        } else {
            ranInt ++;
        }
        int index = Arrays.binarySearch(weights, ranInt);
        if (index < 0) {
            index = -1 - index;
        }
        return nodes[index];
    }

    @Override
    public String toString() {
        StringBuilder l1 = new StringBuilder();
        StringBuilder l2 = new StringBuilder("[random]\t");
        StringBuilder l3 = new StringBuilder("[node]\t\t");
        l1.append(this.getClass().getName()).append(":").append(this.hashCode()).append(":\n").append("[index]\t\t");
        for (int i = 0; i < weights.length; i++) {
            l1.append(i).append("\t");
            l2.append(weights[i]).append("\t");
            l3.append(nodes[i]).append("\t");
        }
        l1.append("\n");
        l2.append("\n");
        l3.append("\n");
        return l1.append(l2).append(l3).toString();
    }
}
RandomUtil.java
/**
 * 随机工具类
 *
 * 使用权重的集合Map构建随机元数据对象
 *
 * 比如:
 * 我们有3个url地址,他们的权重分别为1,2,3现在我们利用RandomUtil来根据权重随机获取url:
 *
 * <p><blockquote><pre>
 *
 * map.put(url1, 1);
 * map.put(url2, 2);
 * map.put(url3, 3);
 * RandomMeta<String, Integer> md = RandomUtil.buildWeightMeta(map);
 * String weightRandomUrl = md.random();
 *
 * </pre></blockquote><p>
 *
 * @author wxf on 14-5-5.
 */
public class RandomUtil {
    public static <T> WeightMeta<T> buildWeightMeta(final Map<T, Integer> weightMap) {
        final int size = weightMap.size();
        Object[] nodes = new Object[size];
        int[] weights = new int[size];
        int index = 0;
        int weightAdder = 0;
        for (Map.Entry<T, Integer> each : weightMap.entrySet()) {
            nodes[index] = each.getKey();
            weights[index++] = (weightAdder = weightAdder + each.getValue());
        }
        return new WeightMeta<T>((T[]) nodes, weights);
    }
}

权重随机的实现

时间: 2024-08-13 17:42:51

权重随机的实现的相关文章

根据权重随机选取指定条数记录的简单算法实现(C#)

一.应用场景: 有时我们需要从一些列数据中根据权重随机选取指定条数记录出来,这里需要权重.随机,我们根据权重越大的,出现概率越大.例如广告系统:可根据客户支付金额大小来调控客户们的广告出现概率,客户支付金额越大,其广告出现频率越频繁,例如:加入有10条广告,然后每条广告都有一个权重,我们每次要根据权重选取5条广告出来进行显示.有了需求,我们就进行解决,本文章就是利用一种简单的算法来实现根据权重来随机选取. 二.简单算法的实现: 根据我们需求,上网找了不少资料,都没有找到一种比较适合的方案,就自己

权重随机算法的java实现

一.概述 平时,经常会遇到权重随机算法,从不同权重的N个元素中随机选择一个,并使得总体选择结果是按照权重分布的.如广告投放.负载均衡等. 如有4个元素A.B.C.D,权重分别为1.2.3.4,随机结果中A:B:C:D的比例要为1:2:3:4. 总体思路:累加每个元素的权重A(1)-B(3)-C(6)-D(10),则4个元素的的权重管辖区间分别为[0,1).[1,3).[3,6).[6,10).然后随机出一个[0,10)之间的随机数.落在哪个区间,则该区间之后的元素即为按权重命中的元素. 实现方法

select random item with weight 根据权重随机选出

http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/ 类似俄罗斯轮盘赌 select random item with weight 根据权重随机选出,布布扣,bubuko.com

带权随机数问题--根据权重随机选择一条路径

最近工作中遇到了一个根据权重随机选择一条路径的问题,一时没有啥好方案,参考借鉴了网上的经验,得出了如下解决方案: 思路:1.求权重的和,对(0,权重之歌和]区间进行划分,每个权重占用长度为权重的区间: 2.产生一个在(0,权重之和]区间的等概率随机数: 3.该随机数落在哪个区间,则该区间对应的权重的映射为本次产生的带权随机数. 1 import java.util.ArrayList; 2 import java.util.HashMap; 3 import java.util.List; 4

加权重随机算法

场景:有N个合作方,每一个合作方都有一定的权重,按权重随机选择一个合作方 typedef struct { string k;//partner_id string v;//value string m;//0:number 1:ratio }Bookpartner_count_listInfo; string GetRandNumRatio( vector<Bookpartner_count_listInfo> arpartner_count_list) { int weight = 0;

Java 模板权重随机

Template templates=...// 所有的模板 final int _weights=1000; // 所有的模板权重 Template _template=null; //随机一个权重 int rand = RandomUtil.nextInt(0, _weights); int lastEd = 0; int curEd = 0; // 根据随机的权重找到对应的模板 for(Template _templ : templates) { int eden = _templ .ge

我的游戏服务器类库 -- 按权重随机选择1个或n个对象

按权重选择 在编写游戏服务器的时候,经常会遇到类似的需求:从列表中随机选出1个或多个条目,且条目是有权重的(权重越大,选中它的可能性就越大).比如说,砍死一个怪物可以从一个装备列表里掉一个装备.这种需求,和现实生活中的幸运大转盘很类似: 算法实现 因为这种需求很常见,所以我想把它写的通用一点.首先,接口Weighted表示有权重值的对象,getWeight()方法返回权重值: public interface Weighted { public int getWeight(); } Weight

权重随机算法

int weightSum = 0; for (Item item : mItems) { weightSum += item.getWeight(); } if (weightSum <= 0) { return null; } Random random = new Random(); int randomNum = random.nextInt(weightSum); Integer m = 0; for (Item item : mItems) { if (m <= randomNum

[LeetCode] Random Pick with Weight 根据权重随机取点

Given an array w of positive integers, where w[i] describes the weight of index i, write a function pickIndex which randomly picks an index in proportion to its weight. Note: 1 <= w.length <= 10000 1 <= w[i] <= 10^5 pickIndex will be called at