windows-nt/Source/XPSP1/NT/inetsrv/query/h/heap.hxx
2020-09-26 16:20:57 +08:00

391 lines
15 KiB
C++

//+---------------------------------------------------------------------------
//
// Microsoft Windows
// Copyright (C) Microsoft Corporation, 1991 - 2001.
//
// File: HEAP.HXX
//
// Contents: heap
//
// Classes: CHeap
//
// History: 08-May-91 BartoszM Created
//
//----------------------------------------------------------------------------
#pragma once
#ifdef DISPLAY_INCLUDES
#pragma message( "#include <" __FILE__ ">..." )
#endif
//+---------------------------------------------------------------------------
//
// Class: CHeap
//
// Purpose: Heap of items: parametrized class
//
// Interface:
// CHeap( int count, CItem * array[] )
// CHeap( int count )
// CHeap ()
// BOOL IsEmpty()
// int Count()
// CItem* GetVector()
// CItem * Top()
// CItem * RemoveTop()
// CItem * RemoveBottom()
// void Add ( CItem * item )
// void Reheap ()
// void MakeHeap ()
// void MakeHeap ( int count, CItem * array[] )
//
// Notes: This heap can be used for any class of elements
// provided there is a function that compares two elements.
// This function can be defined inline. It takes two pointers
// to elements to be compared and returns true if the first
// element is less than the second one. The name of the
// function is passed to the IMP_HEAP macro.
// Both DEF_HEAP and IMP_HEAP take the name of the
// heap class and the name of the element class as parameters.
// All methods preserve the heap property (partial order).
// Top element is accessible for manipulation. If its
// value changes, Reheap should be called explicitly.
//
// Example:
// class CFoo;
// // comparison function
// BOOL LessFoo ( CFoo * f1, CFoo * f2 );
// // Define class CFooHeap
// DEF_HEAP ( CFooHeap, CFoo )
// // Implement methods of CFooHeap
// IMP_HEAP ( CFooHeap, CFoo, LessFoo )
//
// CFoo aFoo [10];
// // initialize the array
// CFooHeap MyHeap ( 10, aFoo );
// CFoo* pFoo = MyHeap.Top(); // smallest element
// pFoo->ChangeValue ( 13 );
// MyHeap.Reheap(); // reorder after manipulation
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
#define DEF_HEAP( CHeap, CItem ) \
class CHeap \
{ \
public: \
CHeap():_end(-1), _item(0) {} \
CHeap( int count, CItem ** array ) \
: _end(count-1), _item(array) \
{ MakeHeap(); } \
CHeap( int count ):_end(-1) \
{ _item = new CItem* [count]; } \
~CHeap(); \
BOOL IsEmpty() {return _end < 0;} \
CItem * Top() { return _item[0]; } \
CItem * RemoveTop(); \
CItem * RemoveTopKey(); \
__forceinline CItem * RemoveBottom() \
{ \
if ( _end >= 0 ) \
return _item [_end--]; \
else \
return 0; \
} \
int Count() const { return _end+1;} \
CItem ** GetVector() { return _item;} \
void Add ( CItem * item ); \
void AddKey ( CItem * item, ULONG key ); \
void Reheap (); \
void ReheapKey (); \
void MakeHeap (); \
void MakeHeap ( int count, CItem ** array ) \
{ _end=count-1; _item = array; MakeHeap(); } \
void CiExtDump(void *ciExtSelf); \
private: \
int _end; \
CItem ** _item; \
};
//+---------------------------------------------------------------------------
//
// Member: CHeap::CHeap, public
//
// Synopsis: Make a heap from an array
//
// Arguments: [count] -- size of an array
// [array] -- array of pointers to elements
//
// Notes: The size of the heap is fixed. No bound checking is done.
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::CHeap, public
//
// Synopsis: Create an empty heap of maximum size defined by count
//
// Arguments: [count] -- size of an array
//
// Notes: The size of the heap is fixed. No bound checking is done.
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::CHeap, public
//
// Synopsis: Create an empty heap
//
// Notes: To be used only in two-step construction -- see: MakeHeap
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::~CHeap, public
//
// Synopsis: Destroy the heap, delete all the elements.
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::IsEmpty, public
//
// Returns: TRUE if empty, FALSE otherwise
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::Top, public
//
// Returns: Top element or NULL if heap empty
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::RemoveBottom, public
//
// Synopsis: Remove last element.
//
// Returns: Bottom element of NULL if heap empty
//
// Notes: Used as destructive iterator.
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::RemoveTop, public
//
// Synopsis: Removes and returns top element
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::Add, public
//
// Synopsis: Add an element to the heap
//
// Arguments: [item] -- item to be added
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::Reheap, public
//
// Synopsis: Reheap after changing the top element (sifts down)
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::MakeHeap, public
//
// Synopsis: Make an ordered heap out of random array.
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
//+---------------------------------------------------------------------------
//
// Member: CHeap::MakeHeap, public
//
// Synopsis: Make an ordered heap from array.
//
// Arguments: [count] -- size of an array
// [array] -- array of pointers to elements
//
// Notes: Use only in two-step construction!
//
// History: 08-May-91 BartoszM Created.
//
//----------------------------------------------------------------------------
// Macro used by Reheap and MakeHeap (for speed)
#define REHEAP(CHeap, CItem, LessThan, iroot) \
\
CItem * root_item = _item[iroot]; \
int parent, child; \
for ( parent = iroot, child = 2 * iroot + 1; \
child <= _end; \
parent = child, child = 2 * child + 1 ) \
{ \
if ( child < _end \
&& LessThan ( _item[child+1], _item[child] ) ) \
child++; \
\
if ( ! LessThan ( _item[child], root_item ) ) \
break; \
\
_item [parent] = _item [child]; \
} \
_item [parent] = root_item;
#define REHEAPKEY(CHeap, CItem, LessThan, iroot, GetKey, KeyType) \
\
CItem * root_item = _item[iroot]; \
KeyType root_key; \
if ( -1 != _end ) \
root_key = GetKey( root_item ); \
int parent, child; \
for ( parent = iroot, child = 2 * iroot + 1; \
child <= _end; \
parent = child, child = 2 * child + 1 ) \
{ \
if ( child < _end \
&& LessThan ( _item[child+1], _item[child] ) ) \
child++; \
\
if ( ! LessThan ( _item[child], root_key ) ) \
break; \
\
_item [parent] = _item [child]; \
} \
_item [parent] = root_item;
//
// Implementation
//
#define IMP_HEAP( CHeap, CItem, LessThan ) \
\
CHeap::~CHeap() \
{ \
for ( int i = 0; i <= _end; i++ ) \
delete _item[i]; \
delete _item; \
} \
\
CItem * CHeap::RemoveTop () \
{ \
if ( IsEmpty() ) \
return 0; \
CItem * ret = Top(); \
if ( _end >= 0 ) \
{ \
_item [0] = _item [_end]; \
_item[_end--] = 0; \
Reheap(); \
} \
return ret; \
} \
\
void CHeap::Add ( CItem * item ) \
{ \
_end++; \
int child, parent; \
for ( child = _end, parent = (_end-1)/2; \
child > 0; \
child=parent, parent = (parent-1)/2) \
{ \
if ( !LessThan( item, _item[parent] )) \
break; \
_item[child] = _item[parent]; \
} \
_item[child] = item; \
} \
\
void CHeap::Reheap () \
{ \
REHEAP (CHeap, CItem, LessThan, 0) \
} \
\
void CHeap::MakeHeap() \
{ \
for ( int iroot = ((_end+1)/2) - 1; \
iroot >= 0; iroot-- ) \
{ \
REHEAP ( CHeap, CItem, LessThan, iroot)\
} \
}
#define IMP_HEAP_KEY( CHeap, CItem, LessThan, GetKey, KeyType ) \
\
void CHeap::AddKey ( CItem * item, KeyType key ) \
{ \
_end++; \
int child, parent; \
for ( child = _end, parent = (_end-1)/2; \
child > 0; \
child=parent, parent = (parent-1)/2) \
{ \
if ( !LessThan( key, _item[parent] )) \
break; \
_item[child] = _item[parent]; \
} \
_item[child] = item; \
} \
\
__forceinline void CHeap::ReheapKey () \
{ \
REHEAPKEY (CHeap, CItem, LessThan, 0, GetKey, KeyType ) \
} \
\
CItem * CHeap::RemoveTopKey () \
{ \
if ( IsEmpty() ) \
return 0; \
CItem * ret = Top(); \
if ( _end >= 0 ) \
{ \
_item [0] = _item [_end]; \
_item[_end--] = 0; \
ReheapKey(); \
} \
return ret; \
} \
\