利用內存chunk充當數據buffer的stack的一個簡單實現

問題描述:

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 







compile and run in visual studio 2005

test result as follows:
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章