比Deque速度快5倍的DequeEx!

wanghao0727 2002-07-05 05:40:13
昨天写完了音频的回放程序,在写音频捕捉程序时,突然有了一个想法,急于想知道它和Deque来比,哪一个速度更快,于是暂停了音频捕捉程序,写了一个DequeEx,经测试,它在进行前插入、后插入、前读取、后读取、随机访问时的时间均为常数n,比Deque的速度快了5倍。但它在进行中间插入和删除时的速度肯定要慢于Deque,因此我没有增加中间插入和删除的方法。有兴趣的朋友可以测试一下。
  其程序代码如下:其中MSGDEQUE定义如下,因为这个已经在DLL中定义了,因此,在测试时,请自己将下面三行代码添加在DequeEx.h文件中:
#include <deque>
using namespace std;
typedef deque<DWORD> MSGDEQUE;

DequeEx.h文件如下:
// DequeEx.h: interface for the DequeEx class.
//
//////////////////////////////////////////////////////////////////////

#if !defined(AFX_DEQUEEX_H__57392FC5_5F59_4B58_B506_2D7B6FB7331C__INCLUDED_)
#define AFX_DEQUEEX_H__57392FC5_5F59_4B58_B506_2D7B6FB7331C__INCLUDED_

#if _MSC_VER > 1000
#pragma once
#endif // _MSC_VER > 1000

enum
{
//设定主要操作的模式。
PUSH_BACK, //主要操作为从后插入。
PUSH_FRONT, //主要操作为从前插入。
PUSH_MIDDLE, //主要操作为从中间插入。
};

//DequeEx是对Dqueue的扩展,它在进行前插、后插、前读取、后读取、随机访问时的速度均为常数n。
//在进行上述操作时的速度,比Dqueue快5倍。

class AFX_EXT_CLASS DequeEx : public CObject
{
public:
void clear(); //清空列表,并释放缓存。
int size(); //得到当前列表中的元素的个数。
bool empty(); //列表是否为空。
DWORD pop_back(); //从列表的尾弹出一个元素。
DWORD pop_front(); //从列表的头弹出一个元素。
void push_front(DWORD value); //将元素放入列表的最前面。
void push_back(DWORD value); //将元素放入列表的最后面。
void SetElementsNoPerBufferAdd(WORD wElementsNoPerAdd); //设置每次缓冲区增加时所增加的元素个数。
void SetFrequentlyAddElementMode(int nMode,WORD wOffset=0); //设置列表频繁进行操作时的方式。
DWORD operator [](int nIndex); //以索引方式直接访问列表中的元素。


//列表在初始化,缺省认为是在列表的两头都进行插入和删除操作。
//如果只想在列表的一边进行插入操作,应该调用SetFrequentlyAddElementMode()方法,
//设定相应的模式,将提高插入元素时的速度。
//如果列表有可能进行保存很多的元素,则应该调用SetElementsNoPerBufferAdd()方法,
//增大每次缓冲区增加的大小,可以明显提高速度。
DequeEx(WORD wElementsNoPerAdd=20, int nMode=PUSH_MIDDLE, WORD wOffset=10);
~DequeEx();

private:
void InitData();
void CheckBuffer();

char* m_pBuffHead; //缓冲区的头指针。
DWORD m_dwBuffSize; //缓冲区的尺寸。
char* m_pBuffTail; //缓冲区的尾指针。
char* m_pHead; //有效数据的始点。
char* m_pTail; //有效数据的尾指针。

WORD m_wElementsNoPerAdd; //每次增加的元素个数。
DWORD m_dwBuffSizePerAdd/*=m_wElementsNoPerAdd*4*/; //每次增加的缓冲区的大小。
DWORD m_dwOffset; //每次改变缓冲区大小时,在m_szEnter前预留的字节个数。
};

#endif // !defined(AFX_DEQUEEX_H__57392FC5_5F59_4B58_B506_2D7B6FB7331C__INCLUDED_)


DequeEx.cpp文件如下:
// DequeEx.cpp: implementation of the DequeEx class.
//
//////////////////////////////////////////////////////////////////////

#include "stdafx.h"
#include "DequeEx.h"

#ifdef _DEBUG
#undef THIS_FILE
static char THIS_FILE[]=__FILE__;
#define new DEBUG_NEW
#endif

//////////////////////////////////////////////////////////////////////
// Construction/Destruction
//////////////////////////////////////////////////////////////////////

DequeEx::DequeEx(WORD wElementsNoPerAdd/*=20*/, int nMode/*=PUSH_MIDDLE*/, WORD wOffset/*=10*/)
{
this->InitData();
this->SetElementsNoPerBufferAdd(wElementsNoPerAdd);
this->SetFrequentlyAddElementMode(nMode,wOffset);
}

DequeEx::~DequeEx()
{

}


void DequeEx::SetElementsNoPerBufferAdd(WORD wElementsNoPerAdd)
{
this->m_wElementsNoPerAdd=wElementsNoPerAdd;
this->m_dwBuffSizePerAdd=this->m_wElementsNoPerAdd*4;
}

void DequeEx::SetFrequentlyAddElementMode(int nMode,WORD wOffset/*=0*/)
{
switch(nMode)
{
//根据操作模式,设定偏移。
case PUSH_BACK:
this->m_dwOffset=0;
break;
case PUSH_FRONT:
this->m_dwOffset=this->m_wElementsNoPerAdd*4;
break;
default:
//缺省时为PUSH_MIDDLE:
if(wOffset>this->m_wElementsNoPerAdd || wOffset==0)
wOffset=this->m_wElementsNoPerAdd/2;
this->m_dwOffset=wOffset*4;
break;
}
}

void DequeEx::CheckBuffer()
{
if(this->m_pHead==NULL)
{
//如果缓冲区为空。
this->m_pBuffHead=new char[this->m_dwBuffSizePerAdd];
this->m_pBuffTail=this->m_pBuffHead+this->m_dwBuffSizePerAdd;
this->m_pHead=this->m_pBuffHead+this->m_dwOffset;
this->m_pTail=this->m_pHead;
this->m_dwBuffSize=this->m_dwBuffSizePerAdd;
}
else
{
//如果数据区已经到了缓冲区的尾。
DWORD dwLen=this->m_pTail-this->m_pHead; //数据的实际长度。
if(dwLen==0)
{
//如果数据区的长度为。
this->m_pHead=this->m_pBuffHead+this->m_dwOffset;
this->m_pTail=this->m_pHead;
}
else if((dwLen+this->m_dwOffset)>=this->m_dwBuffSize)
{
//如果数据区的头与缓冲区头之间的尺寸小于等于设定的偏移尺寸,则增加缓冲。
this->m_dwBuffSize+=this->m_dwBuffSizePerAdd;
char* sz=new char[this->m_dwBuffSize];
memcpy(sz+this->m_dwOffset,this->m_pHead,dwLen);
delete []this->m_pBuffHead;
this->m_pBuffHead=sz;
this->m_pBuffTail=sz+this->m_dwBuffSize;
this->m_pHead=sz+this->m_dwOffset;
this->m_pTail=this->m_pHead+dwLen;
}
else
{
//如果数据区的头与缓冲区头之间的尺寸大于设定的偏移尺寸,则将数据移动到距缓冲区头的偏移尺寸处。
memcpy(this->m_pBuffHead+this->m_dwOffset,this->m_pHead,dwLen);
this->m_pHead=this->m_pBuffHead+this->m_dwOffset;
this->m_pTail=this->m_pHead+dwLen;
}
}
}

void DequeEx::push_back(DWORD value)
{
if((this->m_pTail+4)>this->m_pBuffTail)
this->CheckBuffer();
this->m_pTail[0]=(BYTE)value;
this->m_pTail[1]=(BYTE)(value>>8);
this->m_pTail[2]=(BYTE)(value>>16);
this->m_pTail[3]=(BYTE)(value>>24);
this->m_pTail+=4;
}

void DequeEx::push_front(DWORD value)
{
char* psz=this->m_pHead-4;
if(psz<this->m_pBuffHead || psz>this->m_pBuffTail)
{
this->CheckBuffer();
psz=this->m_pHead-4;
}
psz[0]=(BYTE)value;
psz[1]=(BYTE)(value>>8);
psz[2]=(BYTE)(value>>16);
psz[3]=(BYTE)(value>>24);
this->m_pHead-=4;
}

DWORD DequeEx::pop_front()
{
if(this->m_pHead>=this->m_pTail)
return 0;
DWORD dw=MAKELONG(MAKEWORD(this->m_pHead[0],this->m_pHead[1]),
MAKEWORD(this->m_pHead[2],this->m_pHead[3]));
this->m_pHead+=4;
return dw;
}

DWORD DequeEx::pop_back()
{
if(this->m_pTail<=this->m_pHead)
return 0;
this->m_pTail-=4;
DWORD dw=MAKELONG(MAKEWORD(this->m_pTail[0],this->m_pTail[1]),
MAKEWORD(this->m_pTail[2],this->m_pTail[3]));
return dw;
}

bool DequeEx::empty()
{
return this->m_pTail==this->m_pHead;
}

int DequeEx::size()
{
return (this->m_pTail-this->m_pHead)/4;
}

DWORD DequeEx::operator [](int nIndex)
{
char* psz=this->m_pHead+nIndex*4;
if(psz<this->m_pTail)
return MAKELONG(MAKEWORD(psz[0],psz[1]),MAKEWORD(psz[2],psz[3]));
return 0;
}

void DequeEx::clear()
{
delete []this->m_pBuffHead;
this->InitData();
}

void DequeEx::InitData()
{
this->m_pBuffHead=NULL;
this->m_pBuffTail=NULL;
this->m_pHead=NULL;
this->m_pTail=NULL;
this->m_dwBuffSize=0;
}
...全文
34 1 打赏 收藏 转发到动态 举报
写回复
用AI写文章
1 条回复
切换为时间正序
请发表友善的回复…
发表回复

16,471

社区成员

发帖
与我相关
我的任务
社区描述
VC/MFC相关问题讨论
社区管理员
  • 基础类社区
  • Web++
  • encoderlee
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告

        VC/MFC社区版块或许是CSDN最“古老”的版块了,记忆之中,与CSDN的年龄几乎差不多。随着时间的推移,MFC技术渐渐的偏离了开发主流,若干年之后的今天,当我们面对着微软的这个经典之笔,内心充满着敬意,那些曾经的记忆,可以说代表着二十年前曾经的辉煌……
        向经典致敬,或许是老一代程序员内心里面难以释怀的感受。互联网大行其道的今天,我们期待着MFC技术能够恢复其曾经的辉煌,或许这个期待会永远成为一种“梦想”,或许一切皆有可能……
        我们希望这个版块可以很好的适配Web时代,期待更好的互联网技术能够使得MFC技术框架得以重现活力,……

试试用AI创作助手写篇文章吧