問題描述:
1.stack是計算機中最常用到的數據結構,它主要依據支持後進先出(LIFO)操作抽象而出的一種數據結構;
2.本文嘗試自己封裝一個泛型的stack class,它支持常見的操作;
3.這個類的底層的數據存儲容器是以單鏈表串起來的內存塊(memory chunk )實現,這樣做主要是爲了性能的考量;
4.有個小技巧預先分配一個內存塊和這個鏈表沒關聯,當stack存儲非常少量的東西時,都不用啓用鏈表機制;
5.最後我又封裝一個底層容器爲stl的stack class,這主要是爲了性能比較的考慮;
6.最後我分別比較了以下四種情形的性能:
1)stack class (data container = memory chunk)
2) stack class (data container =list )
3) stack class (data container = vector )
4) st::stack
結論是1最好,3是1的2倍,4比1差一些,2性能非常差;
程序代碼:
#ifndef _ALSTACK_H_
#define _ALSTACK_H_
#include <list>
#include <vector>
#include <stack>
#include "windows.h"
/*
* The class encapsulate simple stack operation
* under interface, it's buffer is made of memory chunk
* compare with array and list in under buffer, it improve performance
*
*
*/
template<class T>
class AlStack
{
public:
AlStack():m_totalCount(0), m_count(0)
{
m_dataBuffer = &m_initBuffer;
}
~AlStack()
{
Clear();
}
void Clear()
{
while( m_dataBuffer != &m_initBuffer )
{
Buffer* buf = m_dataBuffer;
m_dataBuffer = m_dataBuffer->next;
delete buf;
}
}
int Count()
{
return m_totalCount;
}
bool IsEmpty()
{
return m_totalCount == 0;
}
void Push( T& rhs )
{
*Push() = rhs;
}
T& At( int index )
{
assert( index >= 0 && index < m_count );
return m_dataBuffer->buf[m_count - index - 1];
}
const T& At( int index ) const
{
assert( index >= 0 && index < m_count );
return m_dataBuffer->buf[m_count - index - 1];
}
T& Top()
{
assert( m_dataBuffer && m_count > 0 );
return m_dataBuffer->buf[m_count - 1];
}
const T& Top() const
{
assert( m_dataBuffer && m_count );
return m_dataBuffer->buf[m_count - 1];
}
void Pop( T& item )
{
item = Top();
Pop();
}
void Pop()
{
m_totalCount--;
if( --m_count == 0 )
{
if( m_dataBuffer != &m_initBuffer )
{
Buffer* buf = m_dataBuffer;
m_dataBuffer = m_dataBuffer->next;
delete buf;
buf = 0;
// reset the value of m_count
m_count = KSlotCount;
}
}
}
private:
AlStack( const AlStack& rhs )
{
}
AlStack& operator = ( const AlStack& rhs )
{
}
T* Push()
{
if( KSlotCount == m_count )
{
Buffer* buf = new Buffer;
assert( buf );
buf->next = m_dataBuffer;
m_dataBuffer = buf;
//reset the value of value in single buffer
m_count = 0;
}
m_totalCount++;
return &m_dataBuffer->buf[m_count++];
}
private:
enum
{
KSlotCount = 64
};
int m_totalCount;
int m_count;
struct Buffer
{
T buf[KSlotCount];
Buffer* next;
Buffer():next(0)
{
memset( buf, 0x00, sizeof(buf) );
}
};
Buffer m_initBuffer;
Buffer* m_dataBuffer;
};
/*
* The stack implement it's operation by terms of stl container
*
*/
template<class T, class V = std::list<T> >
class StackList
{
public:
StackList():m_dataBuffer()
{
}
~StackList()
{
Clear();
}
void Clear()
{
m_dataBuffer.clear();
}
int Count()
{
return m_dataBuffer.size();
}
bool IsEmpty()
{
return m_dataBuffer.size() == 0;
}
void Push( T& rhs )
{
m_dataBuffer.push_back(rhs);
}
T& Top()
{
assert( m_dataBuffer.size());
return m_dataBuffer.back();
}
const T& Top() const
{
assert( m_dataBuffer.size());
return m_dataBuffer.back();
}
void Pop( T& item )
{
item = m_dataBuffer.back();
Pop();
}
void Pop()
{
m_dataBuffer.pop_back();
}
private:
StackList( const StackList& rhs )
{
}
StackList& operator = ( const StackList& rhs )
{
}
private:
V m_dataBuffer;
};
/*
* Test interface
*
*/
template<class T>
void UnitTestPerformance( T& stackObj, const char* strName )
{
unsigned long start = GetTickCount();
const int len = 640000;
stackObj;
for( int i = 0; i < len; i++ )
{
stackObj.Push( i );
}
for( int i = 0; i < len; i++ )
{
int res = stackObj.Top();
stackObj.Pop();
assert( res == len - i - 1 );
}
assert( stackObj.IsEmpty() == true );
unsigned long interval = GetTickCount() - start;
printf( "%s consume time is %d \n", strName, interval );
}
void StackPerformance( std::stack<int>& stackObj, const char* strName)
{
unsigned long start = GetTickCount();
const int len = 640000;
stackObj;
for( int i = 0; i < len; i++ )
{
stackObj.push( i );
}
for( int i = 0; i < len; i++ )
{
int res = stackObj.top();
stackObj.pop();
assert( res == len - i - 1 );
}
unsigned long interval = GetTickCount() - start;
printf( "%s consume time is %d \n", strName, interval );
}
/*
* Performance compare
*
*/
void TestAlStack()
{
AlStack<int> stackObj;
UnitTestPerformance( stackObj, " the stack of memory chunk" );
StackList<int> stackListObj;
UnitTestPerformance( stackListObj, " the stack of stl list " );
StackList<int, std::vector<int> > stackVecObj;
UnitTestPerformance( stackVecObj, " the stack of stl vector " );
std::stack<int> stackStlObj;
StackPerformance( stackStlObj, " the stack of stl " );
}
#endif