从加权队列中提取元素的算法

问题描述 投票:0回答:1

我正在尝试实现一种“加权队列提取器”,以从具有不同优先级的不同队列中提取元素。我只需选择要从中获取元素的队列。

假设我有 n 个队列,每个队列都有一个优先级。优先级指示相对于其他元素需要从队列中提取多少元素。例如,如果我有 n=2 个队列,其中一个 (A) 的优先级为 5,另一个 (B) 的优先级为 10,那么在从队列中提取 15 次之后,我应该从队列 A 中取出 5 个元素,队列 B 中的 10 个。提取应该统一进行。

举个例子,我应该从队列 B 中提取 2 个元素,然后从队列 A 中提取 1 个元素,依此类推。如果我有 3 个队列 — A、B、C — 优先级分别为 1、3、6,则每 10 次提取应从队列 A 中生成 1 个元素,从队列 B 中生成 3 个元素,从队列 C 中生成 6 个元素。例如,按以下顺序: C B C A C B C C B C(所以我从 A 得到 1,从 B 得到 3,从 C 得到 6)。

我的想法是将每个队列想象成一个跑步者。在此场景中,跑步者 A 速度较慢,以 1 步/秒的速度移动,跑步者 B 的移动速度为 3 秒/秒,跑步者 C 的移动速度为 6 秒/秒。到达终点线的跑步者首先向后退固定距离,A+B+C 步(在本例中,1+3+6=10)。其他人继续按照自己的步调,根据自己的速度走完距离。每次我送某人回来时,我都会从该队列中提取一个元素。考虑这个例子:

 A  B  C
 1  3  6 --> Who is the largest posotive? 6 (i.e., C). I move it back by 10 steps.
 1  3 -4 --> Who is the largest positive? 3 (i.e., B). I move it back by 10 steps. C is negative, so I advance it at its pace (6).
 1 -7  2 --> Who is the largest positive? 2 (i.e., C), and I move it back by 10 steps. B is negative, so I advance it at its pace (3).
 1 -4 -8 --> Who is the largest positive? 1 (i.e., A), and I move it back by 10 steps; B and C are negative, so I advance them at their respective paces.
-9 -1 -2 --> No positive values... I advance them without extracting anyone.
-8  2  4 --> I take the largest positive, the 4 (i.e., C), and move them back by 10 steps, etcetera.
-7  2 -6  --> I get the 2 (aka B) and move it back 10 steps, then I advance the others at their respective paces
-6 -8  0  --> skip
-5 -5  6  --> I get the 6 (aka C) and move it back 10 steps, and let the others run at their pace
-4 -2 -4  --> skip
-3  1  2  --> I get the 2 (aka C) and move him back
-2  1 -8  --> I get 1 (aka B) and move him back
-1 -9 -2  --> skip
 0 -6  4  --> I get 4 (aka C) and move him back  

因此,经过 10,000 次迭代后,我期望从 A 组中提取 1000 个元素,从 B 组中提取 3000 个元素,从 C 组中提取 6000 个元素。但是,我获得了 1346、2885、5769。我怀疑算法中存在错误,但我'我不确定它可能在哪里或是什么。

这是我写的课程:

    import java.util.Arrays;

    public class FairQueue
    {

        private int[] values;
        private int[] priorities;
        private int total = 0;

        public FairQueue(int[] priorities, int[] values)
        {
            this.values = values;
            this.priorities = priorities;
            for (int priority : priorities) {
                total += priority;
            }
            if (this.values == null) {
                this.values = Arrays.copyOf(priorities, priorities.length);
            }
        }

        public int getIndex()
        {
            int toret = -1;
            while (toret == -1) {
                for (int i = 0; i < values.length; i++) {
                    if (values[i] <= 0) {
                        values[i] += priorities[i];
                    } else { // got positive value
                        if (toret == -1) {
                            toret = i;
                        } else { // if I find a better positive
                            if (values[toret] < values[i]) {
                                // should it run? 
                                // values[toret] += priorities[toret];
                                toret = i;
                            }
                        }
                    }

                }
            }
            // go back!
            values[toret] -= total;
            return toret;
        }

        int getTotal()
        {
            return total;
        }

        private static final int ITERATIONS = 1000;
        // with { 1,2,3,4 } it works fine!
        // private static final int[] PRIORITIES = new int[] { 1, 2, 3, 4 };
        private static final int[] PRIORITIES = new int[] { 1, 3, 6 };

        public static void main(String[] args)
        {

            FairQueue f = new FairQueue(PRIORITIES, null);
            int[] res = new int[PRIORITIES.length];
            for (int i = 0; i < ITERATIONS * f.getTotal(); i++) {
                res[f.getIndex()]++;
            }
            for (int i = 0; i < PRIORITIES.length; i++) {
                System.out.println(String.format("p[%d]=%d: %d elemn (%.2f)", i, PRIORITIES[i], res[i],
                        (1.0 * res[i]) / PRIORITIES[i]));
            }


        }

    }


可能,已知前 10 次提取,我可以重复它们......但我更喜欢修复算法。

任何提示将不胜感激。 :)

PS - 我还认为我可以创建一个函数 f(k),给定提取编号,报告确切的队列元素(因此,它是 O(1) 并且不需要算法)。在前面的示例中,f(0)=2(又名 C)、f(5)=1(又名 B)、f(3)=0(又名 A)。

java algorithm queue priority-queue weighted
1个回答
0
投票

我发现算法问题。 每当我找到一个正数时,我就必须提取该元素并减少其相关优先级的值。如果我没有正元素,我必须将队列优先级添加到该值中。示例:

 A  B  C
---------
 1  3  6   ->  A 
-9  3  6   ->  B
-9 -7  6   ->  C
-9 -7 -4
-8 -4  2   ->  C
-8 -4 -8
-7 -1 -2
-6  2  4   ->  B
-6 -8  4   ->  C
-6 -8 -6
-5 -5  0   ->  C
-5 -5 -10 
-4 -2 -4
-4  1  2   ->  B
-4 -9  2   ->  C
-4 -9 -8
-3 -6 -2
-2 -3  4   ->  C
-2 -3 -6
-1  0  0   ->  B
-1 -10 0   ->  C
-1 -10 -10 
 0 -7 -3   ->  A
etc etc

修正算法,结果正确:

    public int getIndex() {
        while (true) {
            for (int i = 0; i < values.length; i++) {
                // any positive value?
                if (values[i] >= 0) {
                    values[i] -= total;
                    return i;
                }
            }
            // no positive values here
            for (int i = 0; i < values.length; i++) {
                values[i] += priorities[i];
            }
        }
    }
© www.soinside.com 2019 - 2024. All rights reserved.