算法 - 查找循环缓冲区中的数字平均值?

时间:2015-04-13 20:29:24

标签: java algorithm

我正在尝试使用一种算法来跟踪循环缓冲区中数字的平均值,假设数字在缓冲区接近容量时被覆盖。

e.g. size = 4 
[1,2,7,3] => avg = 13/4 = 3.25
add(5)
[5,2,7,3] => avg = 17/4 = 4.25

这是我目前的做法。

class CircularBuffer {

    int[] buffer;  
    int head;
    int tail;
    int sum;

    public CircularBuffer(int n) {   
        tail = 0;
        head = 0;
        buffer = new int[n];
    }

    void addNumber(int number) {  
        if (head == tail - 1) {
            sum -= buffer[tail - 1];
        } else if (head != tail - 1) {
            buffer[head++]= number;
            sum += number;
        }

        head = head % buffer.length;                 
    }

    double avg() {        
        if (head > vtail) {
            return sum / (head - tail + 1);
        } else { 
            return sum / buffer.length;
        }
    }

    public static void main(String[] args) {
        CircularBuffer buf = new CircularBuffer(3);
        buf.addNumber(1);
        buf.addNumber(2);
        buf.addNumber(3);
        buf.addNumber(4);
        System.out.println("Avg"+ buf.avg());                     
    }

什么不起作用:目前返回5而不是3。

4 个答案:

答案 0 :(得分:1)

你真的不需要尾巴,你只需要知道你是否达到缓冲区的长度,所以代码看起来像这样:

class CircularBuffer {

    int tail = 0;
    int head = 0;
    int[] buffer;
    int sum = 0;

    public CircularBuffer(int n) {
        buffer = new int[n];
    }

    void addNumber(int number) {
        sum -= buffer[head];
        sum += number;
        buffer[head++] = number;
        head = head % buffer.length;
        if (tail <= buffer.length) {
            tail++;
        }
    }

    double avg() {
        if (head == tail) {
            return (double) sum / (double) head;
        } else {
            return (double) sum / (double) buffer.length;
        }
    }

    public static void main(String[] args) {

        CircularBuffer buf = new CircularBuffer(3);
        buf.addNumber(1);
        buf.addNumber(2);
        buf.addNumber(3);
        buf.addNumber(4);
        System.out.println("Avg" + buf.avg());
    }
}

由于buffer = new int[n];用零填充缓冲区,因此在方法addnumber中不需要任何if / else,只需减去前一个值并添加当前值即可。希望很清楚。

答案 1 :(得分:0)

为什么你只能将平均代码与添加代码分开?

然后你只需要遍历数组,求它并将其除以长度。

答案 2 :(得分:0)

addNumber方法似乎无法正常工作。

首先,如果你想测试你的缓冲区是否已满,你还需要考虑head == tail -1的情况而不是简单的head==length-1 && tail==0

其次,如果缓冲区已满,则需要增加头部和尾部。您可以通过head = (head+1)%length代替简单head++,因为head可能是length-1。尾巴也一样。此外,在这种情况下,您忘记将数字添加到总和中,以及实际将数字插入到后备数组中。

答案 3 :(得分:0)

我稍微修改了你的代码。这是主要方法,基于您在问题中输入的内容。

public static void main(String[] args) {

    CircularBuffer buf = new CircularBuffer(4);
    buf.addNumber(1);
    buf.addNumber(2);
    buf.addNumber(7);
    buf.addNumber(3);
    System.out.println("Avg " + buf.avg());
    buf.addNumber(5);
    System.out.println("Avg " + buf.avg());
}

这是我运行代码时的结果。

Avg 3.25
Avg 4.25

这是我为了让你的代码首先编译,然后正确执行而改变了。

  1. 我添加了一个类声明,并将所有变量都设为类变量。

  2. 不需要头部变量。它总是处于零位。

  3. 我添加了一个布尔值,让我知道循环缓冲区中的值是否被覆盖。

  4. 我在构造函数中初始化了sum和boolean变量bufferFull。

  5. 我重写了addNumber方法,以便总和总是包含正确的值。

  6. 由于sum总是具有正确的值,因此avg方法只计算平均值。

  7. 我格式化了Java代码,以便其他人更容易阅读。

  8. 这是经过修改的代码。

    package com.ggl.testing;
    
    public class CircularBuffer {
    
        private boolean bufferFull;
    
        private int tail;
        private int sum;
    
        private int[] buffer;
    
        public CircularBuffer(int n) {
            this.bufferFull = false;
            this.tail = 0;
            this.sum = 0;
            this.buffer = new int[n];
        }
    
        public void addNumber(int number) {
    
            sum += number;
            if (bufferFull) {
                sum -= buffer[tail];
            }
    
            buffer[tail] = number;
            tail++;
    
            if (tail >= buffer.length) {
                tail = tail % buffer.length;
                bufferFull = true;
            }
        }
    
        public double avg() {
    
            int length = tail;
            if (bufferFull) {
                length = buffer.length;
            }
            return (double) sum / length;
    
        }
    
        public static void main(String[] args) {
    
            CircularBuffer buf = new CircularBuffer(4);
            buf.addNumber(1);
            buf.addNumber(2);
            buf.addNumber(7);
            buf.addNumber(3);
            System.out.println("Avg " + buf.avg());
            buf.addNumber(5);
            System.out.println("Avg " + buf.avg());
        }
    } 
    

    我希望您了解我的所作所为,并将这些原则应用于您的下一个任务。