?? cramsave.h
字號:
//文件名:CRAMSave.h
/*
創建者:徐立
創建日期:2007.08
版權所有@僅供學習交流使用
*/
/*##########################[ 模板使用說明 ]####################################
該模板主要用來存儲大量數據,它能夠對存儲的數據進行快速的遍歷
使用方法:
·將模板實例化:CRAMSave<DATATYPE> RAM; DATATYPE是任意一種數據類型,假設這里的DATATAYPE為int
則為:CRAMSave<int> RAM;
·增加一個對象:int* pTemData=NULL;
pTemData=RAM.GetNewObject();
...... //用pTemData指針對增加的對象賦值
·刪除一個對象:
·修改一個對象:
·對所有的對象進行遍歷,有三種方法.比如要把所有對象的值設成0:
第一種方法(建議使用,要用兩個宏):
int *pTemData=NULL;
BEGIN_LOOP(RAM,pTemData,int) //注意后面不要分號
*pTemData=0;
EDN_LOOP
第二種方法(不建議使用,速度上要遜色很多):
for(int i=1;i<=RAM.GetTotalNum();i++)
{
pTemData=RAM.GetObject(i);
*pTemData=0;
}
第三種方法(不建議使用,要求對模板結構比較熟悉,如果執意要使用,請參考第一種方法中的宏定義)
*/
#ifndef RAMSave_h
#define RAMSave_h 1
#include "StdAfx.h"
#include <list>
using namespace std;
#define MAX_BLOCKNUM 16*256
//******************儲存的基本單元***************//
//成員nIndex的值從1開始;
template<class T>
struct Node
{
T Object;
UINT nIndex;//該對象的編號
UINT nNext;//指向標記。若緊挨著該對象的下一個對象被刪除,nNext=2;若該對象后面連續有
//n個對象被刪除,nNext=n+1;后面緊跟著沒有對象刪除,nNext=1;
};
//***********************************************//
template<class DATATYPE>
class CRAMSave
{
public:
CRAMSave();
~CRAMSave();
public://………………常用函數……………………//
UINT GetTotalNum()const;//獲得對象總個數;
UINT GetEachNum()const;//獲得每塊中存儲的對象個數;
UINT GetBlockNum()const;//獲得塊的個數
UINT GetLastNum()const;//獲得最后一個數據塊的對象數
UINT GetFactTotalNum()const;//獲得實際對象總數
Node<DATATYPE> *GetBlockPtr(UINT blockNO);
//功能:獲取一個新對象
//參數:
//說明: 所獲取的對象為空對象,要用戶自己給新對象賦值
DATATYPE* GetNewObjectPtr();
//功能:獲得一個對象
//參數:(對象編號)
//說明:
DATATYPE* GetObjectPtr(UINT nIndex) ;
//功能:刪除一個對象
//參數:(對象編號)
//說明:
BOOL DeleteObject(UINT nIndex);
//功能:刪除一個對象
//參數:(對象指針)
//說明:
BOOL DeleteObject(DATATYPE* pData);
//功能:獲得一個新對象
//參數:(對象編號)
//說明:
DATATYPE* operator[](UINT nIndex);
//…………………………………………………………………………//
public://………………非常用函數…………………………//
//功能:獲得一個包含對象的節點
//參數:(對象編號)
//說明:
//Node *GetNode(UINT nIndex) const;
//功能:刪除一個節點
//參數:(對象編號)
//說明:
// BOOL DeleteNode(UINT nIndex);
//………………………………………………………………………………//
protected:
BOOL _AddNewBlock();
private:
//***********以下幾個變量,被刪除的對象算在內******************//
UINT m_nBlockNum;//總的塊數
UINT m_nEachNum;//每塊含有的對象個數,每塊的最后一個對象是空的,包括最后一個對象
UINT m_nLastNum;// 最后一塊含有的對象個數;
UINT m_nTotalNum;//所存儲的對象總數,不包括每塊的最后一個對象
//***********************************************************************
private:
UINT m_nFactTotalNum;//所存儲的對象總數,不包括刪除的對象和每塊的最后一個對象
Node<DATATYPE>* m_pBlockHead[MAX_BLOCKNUM];//主要用來存儲每個數據塊的首地址
};
template<class DATATYPE>
CRAMSave<DATATYPE>::CRAMSave()
{
m_nBlockNum=0;
m_nTotalNum=0;
m_nFactTotalNum=0;
m_nEachNum=UINT(64*1024/sizeof(Node<DATATYPE>));
m_nLastNum=0;
for (int i=0;i<MAX_BLOCKNUM;i++)
{
m_pBlockHead[i]=NULL;
}
if(!_AddNewBlock())
{
ASSERT(NULL);
AfxMessageBox("哈哈!怎么受傷的總是你!為電腦加點內存吧! 程序將中斷運行!");
}
}
template<class DATATYPE>
CRAMSave<DATATYPE>::~CRAMSave()
{
for (int i=0;i<m_nBlockNum;i++)
{
delete []m_pBlockHead[i];
}
}
template<class DATATYPE>
UINT CRAMSave<DATATYPE>::GetBlockNum() const
{
return m_nBlockNum;
}
template<class DATATYPE>
UINT CRAMSave<DATATYPE>::GetEachNum() const
{
return m_nEachNum;
}
template<class DATATYPE>
UINT CRAMSave<DATATYPE>::GetTotalNum() const
{
return m_nTotalNum;
}
template<class DATATYPE>
UINT CRAMSave<DATATYPE>::GetFactTotalNum() const
{
return m_nFactTotalNum;
}
template<class DATATYPE>
UINT CRAMSave<DATATYPE>::GetLastNum() const
{
return m_nLastNum;
}
template<class DATATYPE>
Node<DATATYPE>* CRAMSave<DATATYPE>::GetBlockPtr(UINT blockNO)
{
ASSERT(blockNO>0&&blockNO<=m_nBlockNum);
if (blockNO<0||blockNO>m_nBlockNum)
return NULL;
return m_pBlockHead[blockNO-1];
}
template<class DATATYPE>
BOOL CRAMSave<DATATYPE>::_AddNewBlock()
{
Node<DATATYPE>* pTemBlock=NULL;
pTemBlock=new Node<DATATYPE>[m_nEachNum];
if (pTemBlock)
{
for (int i=0;i<m_nEachNum;i++)
{
pTemBlock[i].nIndex=0;
pTemBlock[i].nNext=0;
}
//pTemBlock[m_nEachNum-1]=0;//特殊處理,每塊最后一個對象存儲的偏移量為0(主要是為了防止指針溢出)
m_pBlockHead[m_nBlockNum]=pTemBlock;
m_nBlockNum++;
return TRUE;
}
else return FALSE;
}
template<class DATATYPE>
DATATYPE* CRAMSave<DATATYPE>::GetNewObjectPtr()
{
Node<DATATYPE>* pTemBlock=NULL;
m_nTotalNum++;
m_nFactTotalNum++;
if (m_nLastNum<m_nEachNum-1)
{
pTemBlock=m_pBlockHead[m_nBlockNum-1];
ASSERT(pTemBlock);
pTemBlock[m_nLastNum].nIndex=m_nTotalNum;
pTemBlock[m_nLastNum].nNext=1;
m_nLastNum++;
return &(pTemBlock[m_nLastNum-1].Object);
}
else
{
if(_AddNewBlock())
{
m_nLastNum=1;
pTemBlock=m_pBlockHead[m_nBlockNum-1];
ASSERT(pTemBlock);
pTemBlock[0].nIndex=m_nTotalNum;
return &(pTemBlock[0].Object);
}
ASSERT(NULL);
AfxMessageBox("內存不足耶! 程序將要中斷運行!");
exit(1);
}
}
template<class DATATYPE>
DATATYPE* CRAMSave<DATATYPE>::GetObjectPtr(UINT nIndex)
{
if (nIndex<1||nIndex>m_nTotalNum)
{
ASSERT(NULL);
return NULL;
}
UINT BlockNO=1;
UINT EachNO=1;
UINT ntemVar=0;
ntemVar=UINT(nIndex/m_nEachNum);
EachNO=nIndex-ntemVar*m_nEachNum;
if (0==EachNO) //若剛好是某塊的最后一個對象
return NULL;
Node<DATATYPE>* pTemBlock=NULL;
pTemBlock=m_pBlockHead[ntemVar];
if (0==pTemBlock[EachNO-1].nIndex)
return NULL;
return &(pTemBlock[EachNO-1].Object);
}
template<class DATATYPE>
BOOL CRAMSave<DATATYPE>::DeleteObject(UINT nIndex)
{
if (nIndex<1||nIndex>m_nTotalNum)
return FALSE;
// UINT BlockNO=1;
UINT EachNO=1;
UINT ntemVar=0;
ntemVar=UINT(nIndex/m_nEachNum);
EachNO=nIndex-ntemVar*m_nEachNum;
if (0==EachNO) //若剛好是某塊的最后一個對象
return TRUE;
Node<DATATYPE>* pTemBlock=NULL;
pTemBlock=m_pBlockHead[ntemVar];
if (0==pTemBlock[EachNO-1].nIndex) return TRUE;//若該對象已經被刪除
pTemBlock[EachNO-1].nIndex=0;
for (UINT i=2;i<EachNO+1;i++)//往左邊開始追溯
{
if (0==pTemBlock[EachNO-i].nIndex)//若前一個對象已經被刪除
{
pTemBlock[EachNO-i].nNext=pTemBlock[EachNO-i].nNext+pTemBlock[EachNO-1].nNext;
continue;
}
else
{
pTemBlock[EachNO-i].nNext=pTemBlock[EachNO-i].nNext+pTemBlock[EachNO-1].nNext;
break;
}
}
m_nFactTotalNum--;
return TRUE;
}
template<class DATATYPE>
BOOL CRAMSave<DATATYPE>::DeleteObject(DATATYPE* pData)
{
UINT index=0;
Node<DATATYPE>* pTemBlock=NULL;
for (UINT i=0;i<m_nBlockNum;i++ )
{
pTemBlock=m_pBlockHead[i];
if (0==pTemBlock->nNext)
pTemBlock=pTemBlock+pTemBlock->nNext;
while (0!=pTemBlock->nNext)
{
if (pData==&(pTemBlock->Object))
{
index=pTemBlock->nIndex;
break;
}
pTemBlock=pTemBlock+pTemBlock->nNext;
}
if(index!=0)
break;
}
DeleteObject(index);
return TRUE;
}
template<class DATATYPE>
DATATYPE* CRAMSave<DATATYPE>::operator[](UINT nIndex)
{
if (nIndex<1||nIndex>m_nTotalNum)
{
//AfxMessageBox("所要找的對象不存在! 將返回一個空對象");
return NULL;
}
UINT BlockNO=1;
UINT EachNO=1;
UINT ntemVar=0;
ntemVar=UINT(nIndex/m_nEachNum);
EachNO=nIndex-ntemVar*m_nEachNum;
if (0==EachNO) //若剛好是某塊的最后一個對象
return NULL;
Node<DATATYPE>* pTemBlock=NULL;
pTemBlock=m_pBlockHead[ntemVar];
if (0==pTemBlock[EachNO-1].nIndex)
return NULL;
return &(pTemBlock[EachNO-1].Object);
}
//參數說明:(CRAMSave對象,DATATYPE類型的指針,DATATYPE類型)
#define BEGING_LOOP(RAM,pData,DATATYPE) \
Node<DATATYPE>* pTemBlockMarco=NULL;\
for (UINT nLoopVarMarco=1;nLoopVarMarco<=RAM.GetBlockNum();nLoopVarMarco++ ) {\
pTemBlockMarco=RAM.GetBlockPtr(nLoopVarMarco);\
if (0==pTemBlockMarco->nNext)\
pTemBlockMarco=pTemBlockMarco+pTemBlockMarco->nNext;\
while (0!=pTemBlockMarco->nNext){pData=&(pTemBlockMarco->Object);
#define END_LOOP pTemBlockMarco=pTemBlockMarco+pTemBlockMarco->nNext;\
}\
}
#endif
/*
在后面的宏定義中如果寫成
RAM.GetpBlock()=*(RAM.GetIterator());會報錯
定義一個中間變量即可解決
如果直接在宏其中定義:Node* pp;也會報錯
所以先要把Node 定義在CRAMSave的外面,再在宏中定義:Node<DataType> *pp;即可
注意:宏定義時一定不能有空行
內存開辟時,計算機自動按4字節對齊。如果一個對象大小為m,指針加一,地址上移動m;指針變量的大小是4個字節
*/
?? 快捷鍵說明
復制代碼
Ctrl + C
搜索代碼
Ctrl + F
全屏模式
F11
切換主題
Ctrl + Shift + D
顯示快捷鍵
?
增大字號
Ctrl + =
減小字號
Ctrl + -