【问题标题】:Circular Buffer in Java?Java中的循环缓冲区?
【发布时间】:2016-06-11 08:09:00
【问题描述】:

我需要一个类似双端队列的数据结构,我相信它被称为循环缓冲区。

这就是我所做的。

public class MyStack {


    byte[][] orders = {  {0, 1, 2, 3}, {1, 2, 3, 0}, {2, 3, 0, 1}, {3, 0, 1, 2}  };

    byte state      = 0;

    int[] data      = {1, 2, 3, 4};


    void swap(int value){           
        data[state] = value;

        if(state == 3){
            state = 0;

        }else{
            state ++;

        }       
    }

    int[] dump(){

        int[] output = {  
                          data[  orders[state][0]  ],
                          data[  orders[state][1]  ],
                          data[  orders[state][2]  ],
                          data[  orders[state][3]  ],
                       };

        return output;
    }

}

这里的输出正是我需要的功能类型。它基本上是一个长度为 4 的窗口,通过无限的离散空间或沿数轴移动。

我的问题是:这个解决方案有效吗?是否有为此功能设计的内置库?如果是这样,是否值得使用?

【问题讨论】:

  • 没有pushpop 操作-这是如何实现堆栈ADT?如果您的数据结构不打算像堆栈一样工作,请调用其他名称,否则您会混淆人们。
  • 我不确定堆栈的手动实现与内置实现(经过大量审查)相比如何。我确实认为真正的问题是您遇到了哪些性能/使用问题?如果实现堆栈不是您的目标 - 我相信不使用现有库的开销是不值得的。
  • @Joni 在swap中push和pop都是同时完成的。
  • @Joni 好的,我明白你在说什么。我想 is 并不是真正的堆栈。
  • 这不是堆栈。更多的是“最近添加的固定长度的整数缓冲区”。坦率地说,对于 4 个整数,我真的怀疑任何实现都可能成为应用程序的性能瓶颈。不过,我觉得这个实现并不是特别优雅:由于硬编码的订单数组,它并不是真正可扩展的。您可以只使用状态来创建一个转储,其中包含数据数组的末尾与其开头连接。

标签: java optimization data-structures stack deque


【解决方案1】:

circular buffer 的典型实现使用两个索引来标记队列的第一个和最后一个元素。无需显式存储状态,因为 enqueuedequeue 可以通过索引计算完成。 swap 方法的更好名称是 rotate

您可以删除 orders 数组并将 dump 实现更改为:

    int[] output = {  
                      data[  (state+0)%4  ],
                      data[  (state+1)%4  ],
                      data[  (state+2)%4  ],
                      data[  (state+3)%4  ],
                   };

【讨论】:

  • 我要测试一下。但我想知道,您认为存储状态是否比每次迭代运行四个模数计算更快?
  • 这些函数可能有多达 10 或 20 个同时运行。
  • 如果性能对您很重要,您应该对其进行测试。访问外部阵列存在代价高昂的高速缓存未命中的危险。模数 4 可以优化为按位与 &3。我的直觉是计算会比使用数组更快。
【解决方案2】:

对此的一种改进是,删除大小为 n 的订单二维数组。

byte[][] orders = {  {0, 1, 2, 3}, {1, 2, 3, 0}, {2, 3, 0, 1}, {3, 0, 1, 2}  };

因为如果你知道状态,那么orders数组也可以通过公式动态确定

for(int i =0; i<data.length; i++){
  output[i] = data[(state+i)%data.length];
}

这可以用来返回输出。

【讨论】:

  • 虽然它给你一种改进的感觉,但我更想知道你需要这种类型的 ADT 的情况,如果你能提供一下你的问题需求的描述,我很感激。跨度>
猜你喜欢
  • 2019-06-08
  • 2022-11-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多