Ring buffer环形队列使用

环形缓存区:

       环形缓冲器(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。

 

 

设计思想

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

 

设计思路:

实现思路

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;

}

 

  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值