1.双向队列是程序设计中最常用到的数据结构,它是依据FIFO的操作抽象而出一种数据结构;
2.本文尝试自己封装一个泛型的double queue class,它支持常见的操作;
3.这个类的底层的数据存储容器是以双向链表串起来的内存块(memory chunk )实现,这样做主要是为了性能的考量
4.它支持两边插入和删除操作,其接口功能完全等同于STL 的deque;
5.最后我又封装一个底层容器为STL的deque class,这主要是为了性能比较的考虑;
6.最后我分别比较了以下四种情形的性能:
1)AlDeque class (data container = memory chunk)3) adapter deque class (data container = deque)
7. 性能测试结构发现:
1)相互之间的时间之比基本上10倍关系;#ifndef ALDEQUE_H_ #define ALDEQUE_H_ #include <deque> #include <vector> #include <list> #include "windows.h" /* * a simple double direction queue. it‘s under container is memory chunk which can be list pointer * advantage: 1. good performance compare to stl queue * 2. simple implementation */ template<class T> class AlDeque { public: AlDeque():m_backBuffer(0), m_frontBuffer(0), m_backElemCount(0), m_frontElemCount(0), m_totalCount(0) { } ~AlDeque() { Clear(); } bool IsEmpty() { return m_totalCount == 0; } /* * release all memory * */ void Clear() { Buffer* cur = m_frontBuffer; while( cur != m_backBuffer ) { m_frontBuffer = m_frontBuffer->next; delete cur; cur = 0; cur = m_frontBuffer; } delete m_backBuffer; } /* * retrieve the number of elements inside queue * */ size_t Size() { return m_totalCount; } /* * push element to queue from back * */ void PushBack( const T& data ) { *PushBack() = data; } /* * push element to queue from front * */ void PushFront( const T& data ) { *PushFront() = data; } /* * pop element to queue from back * */ void PopBack() { if( 0 == m_backBuffer ) return; m_totalCount--; m_backElemCount--; if( 0 == m_backElemCount ) { Buffer* cur = m_backBuffer; m_backBuffer = m_backBuffer->prev; delete cur; cur = 0; if( m_backBuffer ) { m_backElemCount = KSlotCount; } else { m_frontBuffer = 0; return; } } } /* * pop element to queue from front * */ void PopFront() { if( 0 == m_frontBuffer ) return; m_totalCount--; m_frontElemCount--; if( 0 == m_frontElemCount ) { Buffer* cur = m_frontBuffer; m_frontBuffer = m_frontBuffer->next; delete cur; cur = 0; if( m_frontBuffer ) { m_frontElemCount = KSlotCount; } else { m_backBuffer = 0; return; } } } /* * retrieve element to queue from front * */ T& Front() { assert( m_frontBuffer && m_frontElemCount ); return m_frontBuffer->buf[KSlotCount - m_frontElemCount]; } /* * retrieve element to queue from back * */ T& Back() { assert( m_backBuffer && m_backElemCount ); return m_backBuffer->buf[ m_backElemCount - 1 ]; } protected: //disallow copy constructor and assignment operator AlDeque( const AlDeque& rhs ) { } AlDeque& operator = ( const AlDeque& rhs ) { } // implementation of push from front T* PushFront() { m_totalCount++; if( 0 == m_frontBuffer ) { m_frontBuffer = new Buffer; assert( m_frontBuffer ); if( 0 == m_backBuffer ) { m_backBuffer = m_frontBuffer; m_backElemCount = KSlotCount; //mark invalid for back insert } m_frontElemCount = 0; } else { if( KSlotCount == m_frontElemCount ) //full currently buffer { Buffer* newBuf = new Buffer; assert( newBuf ); newBuf->next = m_frontBuffer; m_frontBuffer->prev = newBuf; m_frontBuffer = newBuf; m_frontElemCount = 0; } } return &m_frontBuffer->buf[ KSlotCount - (++m_frontElemCount)]; } // implementation of push from back T* PushBack() { m_totalCount++; if( 0 == m_backBuffer ) { m_backBuffer = new Buffer; if( 0 == m_frontBuffer ) { m_frontBuffer = m_backBuffer; m_frontElemCount = KSlotCount; //mark invalid for front insert } m_backElemCount = 0; } else { if( KSlotCount == m_backElemCount ) //full currently buffer { Buffer* newBuf = new Buffer; assert( newBuf ); newBuf->prev = m_backBuffer; m_backBuffer->next = newBuf; m_backBuffer = newBuf; m_backElemCount = 0; } } return &m_backBuffer->buf[m_backElemCount++]; } protected: enum { KSlotCount = 64 }; struct Buffer { T buf[KSlotCount]; Buffer* next; Buffer* prev; Buffer():next(0), prev(0) { memset( buf, 0x00, sizeof(buf) ); } }; Buffer* m_backBuffer; // data buffer corresponding to back operation Buffer* m_frontBuffer; // data buffer corresponding to front operation size_t m_backElemCount; // size_t m_frontElemCount; size_t m_totalCount; // total elements }; /* * adapter class * */ template<class T, class Container = std::list<T> > class DequeAdaptStl { public: DequeAdaptStl():m_dataContainer() { } ~DequeAdaptStl() { m_dataContainer.clear(); } void Clear() { m_dataContainer.clear(); } size_t Size() { return m_dataContainer.size(); } void PushBack( const T& data ) { m_dataContainer.push_back( data ); } void PushFront( const T& data ) { m_dataContainer.push_front( data ); } void PopBack() { m_dataContainer.pop_back(); } void PopFront() { m_dataContainer.pop_front(); } T& Front() { return m_dataContainer.front(); } T& Back() { return m_dataContainer.back(); } protected: Container m_dataContainer; }; /* * unit test * */ template<class container> void UnitTestDeque( container& queObj, const char* str ) { const int len = 64 * 10000; unsigned long start = GetTickCount(); //unit test 1 // insert and pop in corresponding direction { for( int i = 0; i < len; i++ ) { queObj.PushBack( i ); } for( int i = 0; i < len; i++ ) { int sel = queObj.Back(); assert( sel == len - 1 - i ); queObj.PopBack(); } for( int i = 0; i < len; i++ ) { queObj.PushFront( i ); } for( int i = 0; i < len; i++ ) { int sel = queObj.Front(); assert( sel == len - i - 1); queObj.PopFront(); } } //unit test 2 // insert and pop in reverse direction { for( int i = 0; i < len; i++ ) { queObj.PushBack( i ); } for( int i = 0; i < len; i++ ) { int sel = queObj.Front(); assert( sel == i ); queObj.PopFront(); } for( int i = 0; i < len; i++ ) { queObj.PushFront( i ); } for( int i = 0; i < len; i++ ) { int sel = queObj.Back(); assert( sel == i ); queObj.PopBack(); } } //unit test 2 // test release interface { for( int i = 0; i < len; i++ ) { queObj.PushBack( i ); } for( int i = 0; i < len; i++ ) { queObj.PushFront( i ); } queObj.Clear(); } unsigned long interval = GetTickCount() - start; printf( "%s consume time is %d \n", str, interval ); } /* * Test interface * */ void TestAlDeque() { AlDeque<int> alDeque; UnitTestDeque( alDeque, "the deqeue of memory chunk" ); DequeAdaptStl<int> dequeList; UnitTestDeque( dequeList, "the deqeue of container list" ); DequeAdaptStl<int, std::deque<int> > dequeSTL; UnitTestDeque( dequeSTL, "the deqeue really" ); getchar(); } #endif
利用内存chunk充当数据buffer的泛型的双向队列的简单实现,布布扣,bubuko.com
利用内存chunk充当数据buffer的泛型的双向队列的简单实现
原文:http://blog.csdn.net/manthink2005/article/details/24534501