环形缓存区:

       环形缓冲器(ringr buffer),也称作圆形队列(circular queue),循环缓冲区(cyclic buffer),圆形缓冲区(circula buffer),是一种用于表示一个固定尺寸、头尾相连的缓冲区的数据结构,适合缓存数据流。

背景:

     当有大量数据的时候,我们不能存储所有的数据,那么计算机处理数据的时候,只能先处理先来的,那么处理完后呢,就会把数据释放掉,再处理下一个。那么,已经处理的数据的内存就会被浪费掉。因为后来的数据只能往后排队,如过要将剩余的数据都往前移动一次,那么效率就会低下了,肯定不现实,所以,环形队列就出现了。

环形队列  

目的:避免频繁的内存创建取消、分配。内存一直只用了一块。

队列有着先入先出的特性。但是对于队列如果删除队头以后剩下的空间将不会被释放,又由于队列只能由队尾插入这就导致被删除部分的空间被浪费。解决这个问题就是循环队列。循环队列顾名思义就是将队列串起来形成一个类似与环的结构。对照着图很容易理解:

对于原来队列里的操作自然有不同的地方:

  1. 判断满:循环队列的满不再是rear=front 而是改成(rear-front+maxn)%maxn。
  2. 入队操作: data[rear] = x; rear = (rear+1)%maxn;

总体思想就是不让rear和front的值超过maxn的大小。于是就在rear和front自增时候模maxn,其实就是Ring Buffer。

 

环形缓冲区 hadoop 环形缓冲区大小_数据

 

设计思想

空队时指针(下标)front和rear在一起都指向队前方,当有元素进队,则rear后移;有元素出队,则front后移,最后,开始时分配给队的前端不再被利用。为了充分利用队列,顺序队列总是做成一个逻辑上的循环队列。

环形缓冲区 hadoop 环形缓冲区大小_#include_02

 

设计思路:

实现思路

1,调整front指向队列的第一个元素,front初始值=0

2,调整rear指向队列的最后一个元素的后一个位置,希望空出一个空间作为约定,rear的初始值=0

3,队满,条件: (rear+1) % maxSize = front ,则队满,队列最多可存 maxSize-1个数

4,队空,条件:rear == front空

5,队列中有效的数据的个数 (rear-front+maxSize) % maxSize

注意:

空队时rear等于front,满队时必须空一个位置。

 代码实现

#include <iostream>
#include<stdio.h>
#include<string.h>
using namespace std;
template<class T>
//定义最大的字符长度
#define MAXLEN  1024*1024*100
class  runingBuffer
{
public:
runingBuffer(unsigned size) : m_front(0), m_rear(0), m_size(size)
{
m_data = new T[size];
}        
~runingBuffer()
{
delete []m_data;
}
bool isEmpty() const
{
if(m_front == m_rear)
{
return true;
}
else
{
return false;
}
}
bool isFull()
{
if(m_front==(m_rear + 1) % m_size)
{
return true;
}
else
{
return false;
}
}
void pushData(T ele) throw(bad_exception)
{
if(isFull())
{
throw bad_exception();
}
m_data[m_rear] = ele;
m_rear=(m_rear + 1) % m_size;
printf("Xin Zai Ling pushData m_rear[%d], m_size[%d], m_data[%s], ele=%s\n", m_rear, m_size, m_data[m_rear-1].c_str(), ele.c_str());
}
T popData() throw(bad_exception)
{
if(isEmpty())
{
printf("");
throw bad_exception();
}
T tmp = m_data[m_front];
m_front = (m_front + 1)%m_size;
 
return tmp;
}
 
private:
unsigned long long  m_size;
int m_front;
int m_rear;
T*  m_data;
};
int main()
{
#if 0        
//直接读取一个文件
unsigned char ptrs[1024*10]={0};
FILE *fpRead = fopen("yyy.txt","r+");
if(NULL == fpRead)
{
printf("========== Log 123\n");
return 0;
}
fread(ptrs, 10240, 1, fpRead);
runingBuffer<unsigned char> qq(1024*10 + 1);
 
 
for(int j=0; j<1024*10; j++)
{
//printf("========== Log 123\n");
//         printf("0x%02x  ", *(ptrs+j));
qq.pushData(*(ptrs+j));                
}
 
for(int xx=0; xx < 1024*10; xx++)
{
printf("0x%02x ", qq.popData());
}
printf("\n");
 
 
unsigned char tmp[10]={10, 20, 10, 33, 39, 99, 111, 2, 23, 77};
runingBuffer<unsigned char> qqs(10+1);
for(int ii=0; ii < 10; ii++)
{
qqs.pushData(tmp[ii]);        
}
for(int ii=0; ii < 10; ii++)
{
printf("%d ", qqs.popData());
}
printf("\n");
runingBuffer<int> q(5);
q.pushData(1);
    q.pushData(2);
    q.pushData(3);
    q.pushData(4);
    for (int i = 0; i < 4 ; i++)
        cout << q.popData() << endl;
    q.pushData(5);
    q.pushData(5);
    q.pushData(5);
    cout << q.popData() << endl;
    cout << q.popData() << endl;
    cout << q.popData() << endl;
 
#endif 
 
//如果是string类型数据如何传值
std::string tmpstr = "123456789000000008888008789889889897876688668";
//unsigned char temp[4096]={0};
//memcpy(temp, tmpstr.c_str(), tmpstr.size());
runingBuffer<std::string> mm(tmpstr.length() + 1);
mm.pushData(tmpstr);
//for(int jj=0; jj <tmpstr.length(); jj++)
{
  cout<<">>>>>>>"<< mm.popData()<<endl;
}
    return 0;
}