⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 skiplist.hh

📁 Motion JPEG编解码器源代码
💻 HH
📖 第 1 页 / 共 4 页
字号:
#ifndef __SKIPLIST_H__#define __SKIPLIST_H__// This file (C) 2004 Steven Boswell.  All rights reserved.// Released to the public under the GNU General Public License.// See the file COPYING for more information./* A skip list is a sorted data structure with probabilistic balancing   that performs the same functions as balanced-binary-tree sorts of   data structures, but skip lists have lots of unusual avenues for   optimizations not available to binary trees. */#include "config.h"#include <assert.h>#include <stdlib.h>#include <new>#include "mjpeg_types.h"#include "Status_t.h"#include "Allocator.hh"// Define this to compile in code to double-check and debug the skip// list.#ifndef NDEBUG//	#define DEBUG_SKIPLIST#endif // NDEBUGtemplate <class KEY, class VALUE, class KEYFN, class PRED>class SkipList{private:	// The type of a node in the skip list.	struct Node	{		VALUE m_oValue;			// The data held by this node.#ifdef DEBUG_SKIPLIST		int32_t m_nLevel;			// The number of forward pointers in this node.#endif // DEBUG_SKIPLIST		Node *m_pBackward;			// The node before this one.		Node *m_apForward[1];			// The nodes after this one, at all the levels we exist.	};		SkipList (const SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther);	const SkipList<KEY,VALUE,KEYFN,PRED> &operator =			(const SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther);		// Disallow copying and assignment.		enum { HEADERCHUNK = 10 };		// The number of forward pointers in the header.		// Will give good sorting for up to e^10 items.	public:	typedef Allocator<Node,HEADERCHUNK> Allocator;		// The type of node allocator to use.	static Allocator sm_oNodeAllocator;		// The default node allocator.	SkipList (const PRED &a_rPred = PRED(),			Allocator &a_rAlloc = sm_oNodeAllocator);		// Default constructor.  Must be followed by Init().	SkipList (Status_t &a_reStatus, bool a_bAllowDuplicates,			uint32_t a_nRandSeed, const PRED &a_rPred = PRED(),			Allocator &a_rAlloc = sm_oNodeAllocator);		// Constructor.  Specify whether or not duplicates are allowed,		// and provide a random number seed.	void Init (Status_t &a_reStatus, bool a_bAllowDuplicates,			uint32_t a_nRandSeed);		// Construction method.  Specify whether or not duplicates are		// allowed, and provide a random number seed.	virtual ~SkipList (void);		// Destructor.#ifdef DEBUG_SKIPLIST	void Invariant (void) const;		// Thoroughly analyze the skip list for structural integrity.	void SetDebug (bool a_bDebug);		// Set whether to run the skip-list invariant before and after		// methods.#endif // DEBUG_SKIPLIST	//	// Iterator classes.	//		class Iterator;	class ConstIterator;	friend class ConstIterator;	class ConstIterator	{		protected:			friend class SkipList<KEY,VALUE,KEYFN,PRED>;				// Let SkipList access m_pNode.			Node *m_pNode;				// The node we represent.		public:			ConstIterator() { m_pNode = NULL; }			ConstIterator (Node *a_pNode) : m_pNode (a_pNode) {}			ConstIterator (const Iterator &a_rOther)				: m_pNode (a_rOther.m_pNode) {}			const VALUE &operator*() const {return m_pNode->m_oValue; }			ConstIterator& operator++()				{ m_pNode = m_pNode->m_apForward[0];					return *this; }			ConstIterator operator++(int) { ConstIterator oTmp = *this;				++*this; return oTmp; }			ConstIterator& operator--()				{ m_pNode = m_pNode->m_pBackward;					return *this; }			ConstIterator operator--(int) { ConstIterator oTmp = *this;				--*this; return oTmp; }			bool operator== (const ConstIterator &a_rOther) const				{ return (m_pNode == a_rOther.m_pNode) ? true : false; }			bool operator!= (const ConstIterator &a_rOther) const				{ return (m_pNode != a_rOther.m_pNode) ? true : false; }	};	friend class Iterator;	class Iterator : public ConstIterator	{		public:			Iterator() : ConstIterator() {}			Iterator (Node *a_pNode) : ConstIterator (a_pNode) {}			VALUE &operator*() {return ConstIterator::m_pNode->m_oValue; }			Iterator& operator++() { ConstIterator::m_pNode = ConstIterator::m_pNode->m_apForward[0];				return *this; }			Iterator operator++(int) { Iterator oTmp = *this; ++*this;				return oTmp; }			Iterator& operator--() { ConstIterator::m_pNode = ConstIterator::m_pNode->m_pBackward;				return *this; }			Iterator operator--(int) { Iterator oTmp = *this; --*this;				return oTmp; }			bool operator== (const Iterator &a_rOther) const				{ return (ConstIterator::m_pNode == a_rOther.m_pNode) ? true : false; }			bool operator!= (const Iterator &a_rOther) const				{ return (ConstIterator::m_pNode != a_rOther.m_pNode) ? true : false; }	};		//	// Skip list methods.	//		Iterator Begin (void)			{ return Iterator (m_pHeader->m_apForward[0]); }		// Return an iterator to the beginning of the list.		ConstIterator Begin (void) const			{ return ConstIterator (m_pHeader->m_apForward[0]); }		// Return an iterator to the beginning of the list.		Iterator End (void) { return Iterator (m_pHeader); }		// Return an iterator to the end of the list.		ConstIterator End (void) const { return ConstIterator (m_pHeader); }		// Return an iterator to the end of the list.		uint32_t Size (void) const { return m_nItems; }		// Return the number of items in the list.		// (May be called on a default-constructed object, making it		// possible for default-constructed subclasses/owners to destroy		// themselves safely.)		bool Empty (void) const { return (m_nItems == 0) ? true : false; }		// Return whether the list is empty.		// A structure used to return the result of an insertion.	struct InsertResult	{		Iterator m_itPosition;			// Where the item was inserted, or where the duplicate was			// found.		bool m_bInserted;			// true if the item was inserted into the list.	};		InsertResult Insert (Status_t &a_reStatus, const VALUE &a_rValue);		// Insert an item into the list.		Iterator Insert (Status_t &a_reStatus, Iterator a_oPosition,			const VALUE &a_rValue);		// Insert an item into the list, at this exact location, if it's		// safe.  Returns where it was really inserted.		void Insert (Status_t &a_reStatus, ConstIterator a_oFirst,			ConstIterator a_oLast);		// Insert a range of items from another skip-list.		Iterator Erase (Iterator a_oHere);		// Erase the item here.  Return the item following the one		// removed.		Iterator Erase (Iterator a_oFirst, Iterator a_oLast);		// Erase a range of items in this list.  Return the item		// following the last one removed.		void Clear (void);		// Empty the list.		InsertResult Move (SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther,			Iterator a_oHere);		// Remove an item from another skip list and insert it into		// ourselves.		// Just like an Erase() followed by an Insert(), except that		// there's no possibility of the operation failing.		void Move (SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther,			Iterator a_oFirst, Iterator a_oLast);		// Remove a range of items from another skip-list and insert		// them into ourselves.		// Just like an Erase() followed by an Insert(), except that		// there's no possibility of the operation failing.		void Move (SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther);		// Move all items from the other skip-list to ourself.		// The current skip-list must be empty.		bool CanMove (const SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther) const;		// Returns true if the two skip lists can move items between		// each other.	void Assign (Status_t &a_reStatus,			const SkipList<KEY,VALUE,KEYFN,PRED> &a_rOther);		// Assign the contents of the other skip list to ourselves.		Iterator Find (const KEY &a_rKey);		// Find the given item in the list.  Returns End() if not found.		ConstIterator Find (const KEY &a_rKey) const;		// Find the given item in the list.  Returns End() if not found.		Iterator LowerBound (const KEY &a_rKey);		// Return the position of the first item that's >= the key.		ConstIterator LowerBound (const KEY &a_rKey) const;		// Return the position of the first item that's >= the key.		Iterator UpperBound (const KEY &a_rKey);		// Return the position of the first item that's > the key.		ConstIterator UpperBound (const KEY &a_rKey) const;		// Return the position of the first item that's > the key.private:		Allocator &m_rNodeAllocator;		// Where we get memory to allocate nodes.	bool m_bAllowDuplicates;		// true if we allow duplicate elements.		int16_t m_nHeaderLevel;		// How many valid pointers m_pHeader[] is holding.		Node *m_pHeader;		// The beginning of the list.		Node *m_pSearchFinger, *m_pSearchFinger2;		// Used to speed up searches, by caching the results of		// previous searches.		uint32_t m_nItems;		// The number of items in this list.	uint32_t m_nRandSeed;		// The random-number seed.	KEYFN m_oKeyFn;		// How we extract a key from a value.	PRED m_oPred;		// How we compare keys to each other.		void SearchLower (const KEY &a_rKey, Node *a_pTraverse) const;		// Search for an item greater than or equal to a_rKey.		bool SearchExact (Node *a_pKey, Node *a_pTraverse) const;		// Search for this exact item.  Returns true if it's found.		void SearchUpper (const KEY &a_rKey, Node *a_pTraverse) const;		// Search for an item greater than a_rKey.	void SearchEnd (Node *a_pTraverse) const;		// Point to the end of the list.		void InsertNode (Node *a_pNewNode, int16_t a_nNewLevel,			Node *a_pTraverse);		// Insert a new node into the skip list.  Assume a_pTraverse is		// set up.	Node *RemoveNode (Node *a_pToRemove, Node *a_pTraverse,			int16_t *a_rpLevel = NULL);		// Remove the given node from the skip list.  Assume a_pTraverse		// is set up.		// Returns the node that got removed, and optionally backpatches		// its level.	Node *GetNewNode (int16_t a_nForwardPointers);		// Allocate a new node with the given number of forward		// pointers.  Returns NULL if something goes wrong.	Node *GetNewNodeOfRandomLevel (int16_t &a_rnLevel);		// Allocate a new node with a random number of forward pointers.		// Returns NULL if something goes wrong; otherwise, a_rnLevel		// gets backpatched with the number of levels.	void DeleteNode (int16_t a_nForwardPointers, Node *a_pToDelete);		// Delete a node.	void DeallocateNode (int16_t a_nForwardPointers, Node *a_pToDelete);		// Deallocate a node's storage.	int16_t Rand (void);		// Get another random number.#ifdef DEBUG_SKIPLIST	bool m_bDebug;		// true if the invariant should be checked.#endif // DEBUG_SKIPLIST};// The default node allocator.  Allocates 64K at a time.template <class KEY, class VALUE, class KEYFN, class PRED>typename SkipList<KEY,VALUE,KEYFN,PRED>::Allocator	SkipList<KEY,VALUE,KEYFN,PRED>::sm_oNodeAllocator (65536);// Default constructor.  Must be followed by Init().template <class KEY, class VALUE, class KEYFN, class PRED>SkipList<KEY,VALUE,KEYFN,PRED>::SkipList (const PRED &a_rPred,		Allocator &a_rAlloc)	: m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred){	// Set up some defaults.	m_bAllowDuplicates = false;	m_nHeaderLevel = 0;	m_pHeader = NULL;	m_pSearchFinger = NULL;	m_pSearchFinger2 = NULL;	m_nItems = 0;	m_nRandSeed = 0;#ifdef DEBUG_SKIPLIST	m_bDebug = false;		// Make sure we're intact.	Invariant();#endif // DEBUG_SKIPLIST}// Constructor.  Specify whether or not duplicates are allowed, and// provide a random number seed.template <class KEY, class VALUE, class KEYFN, class PRED>SkipList<KEY,VALUE,KEYFN,PRED>::SkipList (Status_t &a_reStatus,		bool a_bAllowDuplicates, uint32_t a_nRandSeed,		const PRED &a_rPred, Allocator &a_rAlloc)	: m_rNodeAllocator (a_rAlloc), m_oPred (a_rPred){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);		// Set up some defaults.	m_bAllowDuplicates = false;	m_nHeaderLevel = 0;	m_pHeader = NULL;	m_pSearchFinger = NULL;	m_pSearchFinger2 = NULL;	m_nItems = 0;	m_nRandSeed = 0;#ifdef DEBUG_SKIPLIST	m_bDebug = false;#endif // DEBUG_SKIPLIST		// Init() does all the work.	Init (a_reStatus, a_bAllowDuplicates, a_nRandSeed);}// Construction method.  Specify whether or not duplicates are allowed,// and provide a random number seed.template <class KEY, class VALUE, class KEYFN, class PRED>voidSkipList<KEY,VALUE,KEYFN,PRED>::Init (Status_t &a_reStatus,	bool a_bAllowDuplicates, uint32_t a_nRandSeed){	// Make sure they didn't start us off with an error.	assert (a_reStatus == g_kNoError);		// Make sure we haven't been initialized already.	assert (m_pHeader == NULL);		// Fill in the blanks.	m_bAllowDuplicates = a_bAllowDuplicates;	m_nHeaderLevel = 0;	m_nItems = 0;	m_nRandSeed = a_nRandSeed;		// Allocate our necessary nodes.	m_pHeader = GetNewNode (HEADERCHUNK);	m_pSearchFinger = GetNewNode (HEADERCHUNK);	m_pSearchFinger2 = GetNewNode (HEADERCHUNK);	if (m_pHeader == NULL || m_pSearchFinger == NULL		|| m_pSearchFinger2 == NULL)	{		delete m_pHeader;		m_pHeader = NULL;		delete m_pSearchFinger;		m_pSearchFinger = NULL;		delete m_pSearchFinger2;		m_pSearchFinger2 = NULL;		a_reStatus = g_kOutOfMemory;		return;	}		// Set up our nodes.	//	// The way we work, incrementing End() gets you Begin(), and	// decrementing Begin() gets you End().  We implement that by using	// our header node as a NULL-like sentinel node.	m_pHeader->m_pBackward = m_pHeader;	m_pSearchFinger->m_pBackward = m_pHeader;	m_pSearchFinger2->m_pBackward = m_pHeader;	for (int16_t nI = 0; nI < HEADERCHUNK; nI++)	{		m_pHeader->m_apForward[nI] = m_pHeader;		m_pSearchFinger->m_apForward[nI] = m_pHeader;		m_pSearchFinger2->m_apForward[nI] = m_pHeader;	}	#ifdef DEBUG_SKIPLIST	// Make sure we're intact.	Invariant();#endif // DEBUG_SKIPLIST}// Destructor.

⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -