★ wanayoo — archive 1999 http://codeguru.developer.com/cpp_mfc/sortable_cobarray.shtmlNouvelle recherche | Portail wanayoo
EarthWeb
Developer.com Click Here!
Click Here!
Find:
 

EXPERT SEARCH
SEARCH THE IT WEB -----
Site
windows 2000
visual c++
java
visual basic
javascripts
recommend it
 
Contest
mfc codeguru
submission guidelines
 
Book
thinking in c++
stl programmer's guide
reviews
 
Interact
forums
newsgroups
guest book
jobs
jokes
open faq
what's new
 
Other
about
links
newsletters
privacy
tools
 

-----
Visual C++ by E-mail:

Get the weekly e-mail highlights on
Visual C++!
-----



EarthWeb Sites:
IT Management
Networking & Telecommunications
IT Jobs
Software Development
Hardware & Systems
Commerce
Community

EarthWeb Worldwide

   

Sortable CObArray class


This article was contributed by Douglas Peterson.



// SortableObArray.h
/////////////////////////////////////////////////////////////////////

class CSortableObArray : public CObArray
{
public:
	void Sort(int(*CompareFunc)(CObject* pFirst, CObject* pSecond));
	void Sort(int iStartPos, int iElements, int(*CompareFunc)(CObject* pFirst, CObject* pSecond));
};


template< class TYPE >
class CTypedSortableObArray : public CSortableObArray
{
public:
	// Accessing elements
	TYPE GetAt(int nIndex) const
	{ return (TYPE)CSortableObArray::GetAt(nIndex); }
	TYPE& ElementAt(int nIndex)
	{ return (TYPE&)CSortableObArray::ElementAt(nIndex); }
	void SetAt(int nIndex, TYPE ptr)
	{ CSortableObArray::SetAt(nIndex, ptr); }
	
	// Potentially growing the array
	void SetAtGrow(int nIndex, TYPE newElement)
	{ CSortableObArray::SetAtGrow(nIndex, newElement); }
	int Add(TYPE newElement)
	{ return CSortableObArray::Add(newElement); }
	int Append(const CTypedPtrArray< CSortableObArray, TYPE >& src)
	{ return CSortableObArray::Append(src); }
	void Copy(const CTypedPtrArray< CSortableObArray, TYPE >& src)
	{ CSortableObArray::Copy(src); }
	
	// Operations that move elements around
	void InsertAt(int nIndex, TYPE newElement, int nCount = 1)
	{ CSortableObArray::InsertAt(nIndex, newElement, nCount); }
	void InsertAt(int nStartIndex, CTypedSortableObArray< TYPE >* pNewArray)
	{ CSortableObArray::InsertAt(nStartIndex, pNewArray); }
	
	// overloaded operator helpers
	TYPE operator[](int nIndex) const
	{ return (TYPE)CSortableObArray::operator[](nIndex); }
	TYPE& operator[](int nIndex)
	{ return (TYPE&)CSortableObArray::operator[](nIndex); }
	
	void Sort( int(*CompareFunc)(TYPE pFirstObj, TYPE pSecondObj) )
	{ CSortableObArray::Sort((int(*)(CObject*,CObject*))CompareFunc); }
	void Sort( int iStartPos, int iElements, int(*CompareFunc)(TYPE pFirstObj, TYPE pSecondObj) )
	{ CSortableObArray::Sort(iStartPos, iElements, (int(*)(CObject*,CObject*))CompareFunc); }
};



// SortableObArray.cpp
///////////////////////////////////////////////////////////////////

#define STRIDE_FACTOR 3

void CSortableObArray::Sort(int(*CompareFunc)(CObject* pFirst, CObject* pSecond))
{
	// CompareFunc is expected to return a positive integer if pFirstObj
	// should follow pSecondObj (is greater than)
	
	// Uses Shell Sort
	
	// Basically it does a bunch of smaller insertion sorts than insertion sorts the
	//  whole thing.  Insertion sorting is much faster on a list that is already
	//  mostly sorted.
	
	// ** NOTE:  Because GetSize() is called to retrieve the number of elements, you should
	//            call SetSize() with the number of valid elements.  An alternative is
	//            shown in the sort function below.
	
	ASSERT_VALID(this);
	
	BOOL bFound;
	int iElements = GetSize();
	int iInner,iOuter,iStride = 1;
	CObject *pTmp;
	
	while (iStride <= iElements)
		iStride = iStride * STRIDE_FACTOR + 1;
	
	while (iStride > (STRIDE_FACTOR - 1))
	{
		iStride = iStride / STRIDE_FACTOR;
		for (iOuter = iStride; iOuter < iElements; iOuter++)
		{
			bFound = 0;
			iInner = iOuter - iStride;
			while ((iInner >= 0) && !bFound)
			{
				if (CompareFunc(m_pData[iInner+iStride],m_pData[iInner]) < 0)
				{
					pTmp = m_pData[iInner+iStride];
					m_pData[iInner+iStride] = m_pData[iInner];
					m_pData[iInner] = pTmp;
					iInner -= iStride;
				}
				else
					bFound = 1;
			}
		}
	}
}

void CSortableObArray::Sort(int iStartPos, int iElements, int(*CompareFunc)(CObject* pFirst, CObject* pSecond))
{
	// This variation allows you to sort only a portion of the array
	
	ASSERT_VALID(this);
	ASSERT( iStartPos >= 0 && iStartPos <= GetUpperBound() );
	ASSERT( GetSize() - iStartPos >= iElements );
	
	BOOL bFound;
	int iInner,iOuter,iStride = 1;
	CObject *pTmp;
	CObject **pData = &m_pData[iStartPos];
	
	while (iStride <= iElements)
		iStride = iStride * STRIDE_FACTOR + 1;
	
	while (iStride > (STRIDE_FACTOR - 1))
	{
		iStride = iStride / STRIDE_FACTOR;
		for (iOuter = iStride; iOuter < iElements; iOuter++)
		{
			bFound = 0;
			iInner = iOuter - iStride;
			while ((iInner >= 0) && !bFound)
			{
				if (CompareFunc(pData[iInner+iStride],pData[iInner]) < 0)
				{
					pTmp = pData[iInner+iStride];
					pData[iInner+iStride] = pData[iInner];
					pData[iInner] = pTmp;
					iInner -= iStride;
				}
				else
					bFound = 1;
			}
		}
	}
}



// Usage
//////////////////////////////////////////////////////////

// Create a CObject based class
class CMyObject : public CObject
{
public:
    CString name;
    static int CompBackward(CMyObject* pFirstObj, CMyObject* pSecondObj)
    {
        return -lstrcmp((LPCTSTR)pFirstObj->name,(LPCTSTR)pSecondObj->name);
    }
};

// Create an array object
CTypedSortableObArray< CMyObject* > array;

array.SetSize(10);

// Fill the array with a bunch of objects
for (int i=0; i < 10; i++)
{
	CMyObject * pObj = new CMyObject;
	pObj->name.Format("Object #%d",i);
	array[i] = pObj;
}

// Sort the array
array.Sort(CMyObject::CompBackward);

// Display the contents of the now sorted array
for (int i=0; i < 10; i++)
{
	TRACE1("%s\n",array[i]->name);
}


Comments:

Add Comment

   

Give them a visit Click Here!

Click Here!

INSTANT EXPERTS!
Savvy IT Pros report on SupportSource. Take a look inside the largest vault of multi-vendor computing specs ever assembled. Click here for an In-depth Report,.

For tons of Windows technology resources, check out the Windows Programming directory.

Searching the Web for tech topics just got better with
TechCrawler where all results come only from popular technical sites.

WINNER!!!
Congratulations to James Hole, of New Mexico! The grand prize winner of EarthWeb's Flatten the Obstacles Sweepstakes and now a proud Hummer(R) owner.

Give them a visit Click Here!

Click Here!

Click Here!

Click Here!

Home About Us Search Subscribe Advertising Info Contact Us FAQs
Use of this site is subject to certain Terms & Conditions.
Earthweb's statement regarding our users' right to privacy.
Copyright ©1996-2000 EarthWeb Inc.. All rights reserved. Reproduction in whole or in part in any form or medium without express written permission of EarthWeb is prohibited.