编程珠玑——排序算法

编程珠玑第11章讲解的几种排序算法的C++实现

#include "stdafx.h"
#include 
#include 
#include 
#include "windows.h"
using namespace std;

template< typename InPos >
inline void isort( InPos posBegin_, InPos posEnd_ )
{
	/// 通过_Val_type函数获取到迭代器指向的数据类型
	_isort(posBegin_, posEnd_, _Val_type(posBegin_));
}

/// 插入排序,最坏情况下为O(n^2)
template< typename InPos, typename ValueType >
void _isort( InPos posBegin_, InPos posEnd_, ValueType* )
{
	/****************************************************************************
	*	伪代码如下:
	*		for i = [1, n)
	*			t = x[i]
	*			for( j = i; j > 0 && x[j-1] > t; j-- )
	*				x[j] = x[j-1]
	*			x[j] = x[j-1]
	****************************************************************************/
	if( posBegin_ == posEnd_ )
	{
		return;
	}

	/// 循环迭代,将每个元素插入到合适的位置
	for( InPos pos = posBegin_; pos != posEnd_; ++pos )
	{
		ValueType Val = *pos;
		InPos posPrev = pos;
		InPos pos2 = pos;
		/// 当元素比前一个元素大时,交换
		for( ;pos2 != posBegin_ && *(--posPrev) > Val ; --pos2 )
		{
			*pos2 = *posPrev;
		}
		*pos2 = Val;
	}
}

/// 快速排序1,平均情况下需要O(nlogn)的时间
template< typename InPos >
inline void qsort1( InPos posBegin_, InPos posEnd_ )
{
	/****************************************************************************
	*	伪代码如下:
	*		void qsort(l, n)
	*			if(l >= u)
	*				return;
	*			m = l
	*			for i = [l+1, u]
	*				if( x[i] < x[l]
	*					swap(++m, i)
	*			swap(l, m)
	*			qsort(l, m-1)
	*			qsort(m+1, u)
	****************************************************************************/
	if( posBegin_ == posEnd_ )
	{
		return;
	}

	/// 将比第一个元素小的元素移至前半部
	InPos pos = posBegin_;
	InPos posLess = posBegin_;
	for( ++pos; pos != posEnd_; ++pos )
	{
		if( *pos < *posBegin_ )
		{
			swap( *pos, *(++posLess) );
		}
	}

	/// 把第一个元素插到两快元素中央
	swap( *posBegin_, *(posLess) );

	/// 对前半部、后半部执行快速排序
	qsort1(posBegin_, posLess);
	qsort1(++posLess, posEnd_);
};

/// 快速排序2,原理与1基本相同,通过两端同时迭代加快平均速度
template
void qsort2( InPos posBegin_, InPos posEnd_ )
{
	if( distance(posBegin_, posEnd_) <= 0 )
	{
		return;
	}

	InPos posL = posBegin_;
	InPos posR = posEnd_;

	while( true )
	{
		/// 找到不小于第一个元素的数
		do
		{
			++posL;
		}while( *posL < *posBegin_ && posL != posEnd_ );
		
		/// 找到不大于第一个元素的数
		do 
		{
			--posR;
		} while ( *posR > *posBegin_ );

		/// 两个区域交叉时跳出循环
		if( distance(posL, posR) <= 0 )
		{
			break;
		}
		/// 交换找到的元素
		swap(*posL, *posR);
	}

	/// 将第一个元素换到合适的位置
	swap(*posBegin_, *posR);
	/// 对前半部、后半部执行快速排序2
	qsort2(posBegin_, posR);
	qsort2(++posR, posEnd_);
}

/// 当元素个数小与g_iSortMax时使用插入排序,g_iSortMax是根据STL库选取的
const int g_iSortMax = 32;
/// 该排序算法是快速排序与插入排序的结合
template
void qsort3( InPos posBegin_, InPos posEnd_ )
{
	if( distance(posBegin_, posEnd_) <= 0 )
	{
		return;
	}

	/// 小与g_iSortMax时使用插入排序
	if( distance(posBegin_, posEnd_) <= g_iSortMax )
	{
		return isort(posBegin_, posEnd_);
	}

	/// 大与g_iSortMax时使用快速排序
	InPos posL = posBegin_;
	InPos posR = posEnd_;

	while( true )
	{
		do
		{
			++posL;
		}while( *posL < *posBegin_ && posL != posEnd_ );

		do 
		{
			--posR;
		} while ( *posR > *posBegin_ );

		if( distance(posL, posR) <= 0 )
		{
			break;
		}
		swap(*posL, *posR);
	}
	swap(*posBegin_, *posR);
	qsort3(posBegin_, posR);
	qsort3(++posR, posEnd_);
}

int random( int iStart_, int iEnd_ )
{
	return iStart_ + rand()%(iEnd_ - iStart_);
}

int _tmain(int argc, _TCHAR* argv[])
{
	srand(unsigned int(time(0)));

	vector coll;
 	for( int i = 0; i< 100000; ++i )
 	{
 		coll.push_back(random(0, 10000));
 	}
	
 	DWORD dwStart, dwEnd;

	vector collCopy(coll);
	dwStart = GetTickCount();
  	isort(collCopy.begin(), collCopy.end());
  	dwEnd = GetTickCount();
 	cout << dwEnd - dwStart << endl;

	vector collCopy2(coll);
	dwStart = GetTickCount();
	qsort1(collCopy2.begin(), collCopy2.end());
	dwEnd = GetTickCount();
	cout << dwEnd - dwStart << endl;

	vector collCopy3(coll);
	dwStart = GetTickCount();
	qsort2(collCopy3.begin(), collCopy3.end());
	dwEnd = GetTickCount();
	cout << dwEnd - dwStart << endl;

	vector collCopy4(coll);
	dwStart = GetTickCount();
	qsort3(collCopy4.begin(), collCopy4.end());
	dwEnd = GetTickCount();
	cout << dwEnd - dwStart << endl;

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值