【算法导论】快速排序实现

#ifndef QUICK_SORT_H
#define QUICK_SORT_H

#define QK_SORT

#include <iterator>
#include <cmath>
#include "INSERTION-SORT.h"

#ifdef _DEBUG
#include <iostream>
#endif // _DEBUG

//
// 算法思路:
//		每次都挑出一个数,并将比这个数小的数放在此数左边
//		将比这个数大的数都放在此数右边,于是一次划分就形成了
//		再递归的对划分出来的数组调用这个划分方法,知道结束;
//		而这个划分花费的时间为o(n);
//		如果每次都能大概划分为两个相等的序列,那么递归树的深度将是lgn
//		所以算法复杂度为nlg(n);
//		最差深度是n,所以最差的复杂度为n^2;这个最坏情况往往出现在排好序的序列上
//

template <typename T>
struct quick_sort_less
{
	bool operator() (T lhs, T rhs)
		{ return lhs < rhs;}
};

template <typename RandomAccessIterator, typename Val>
void swap_aux(RandomAccessIterator left, RandomAccessIterator right, Val*)
{
	Val tmp = *left;
	*left = *right;
	*right = tmp;
}

template <typename RandomAccessIterator>
void swap(RandomAccessIterator lhs, RandomAccessIterator rhs)
{
	if (lhs == rhs) return;
	swap_aux(lhs, rhs, std::_Val_type(lhs));
}

template <typename RandomAccessIterator, typename Compare>
RandomAccessIterator quick_sort_partition(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	RandomAccessIterator ptr	= first;
	RandomAccessIterator index	= first;
	RandomAccessIterator key	= last - 1;

	for (; index != key; ++index)
	{
		if (comp(*index, *key))
		{
			swap(index, ptr++);
		}
	}

	swap(index, ptr);
	
	return ptr;
}

template <typename RandomAccessIterator, typename Compare>
void quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	if (last - first <= 1) return;
	
	RandomAccessIterator mid = quick_sort_partition(first, last, comp);

#ifdef QK_SORT
	std::cout << *mid << " " << mid - first << std::endl;
#endif // QK_SORT

	quick_sort(first, mid++, comp);
	quick_sort(mid, last, comp);
}

template <typename RandomAccessIterator, typename Compare>
RandomAccessIterator randomized_quick_sort_partition(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	RandomAccessIterator index = first;
	RandomAccessIterator left_index = first;
	RandomAccessIterator key_candidate = rand() % (last - first) + first;
	RandomAccessIterator key = last - 1;

	swap(key, key_candidate);

	for (; index != last; ++index)
	{
		if (comp(*index, *key))
		{
			swap(left_index++, index);
		}
	}

	swap(key, left_index);

	return left_index;
}

template <typename RandomAccessIterator, typename Compare>
void randomized_quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	if (last - first <= 1) return;

	RandomAccessIterator mid = randomized_quick_sort_partition(first, last, comp);

	randomized_quick_sort(first, mid++, comp);
	randomized_quick_sort(mid, last, comp);
}

template <typename RandomAccessIterator, typename Compare, typename _Size>
void _optimized_quick_sort_aux(RandomAccessIterator first, RandomAccessIterator last, Compare comp, _Size key_size)
{
	if (last - first < key_size) return;

	RandomAccessIterator mid = randomized_quick_sort_partition(first, last, comp);

	_optimized_quick_sort_aux(first, mid++, comp, key_size);
	_optimized_quick_sort_aux(mid, last, comp, key_size);
}

template <typename RandomAccessIterator, typename Compare, typename _Size>
void _optimized_quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp, _Size*)
{
	// Get the key size where quick sort dont make effect
	// when the array was divided into some kind of size 
	// that less than the key size (At that time, we use insertion sort
	// to make this sort function more effective)
	_Size key_size = std::log(_Size(last - first)) / std::log(2);

#ifdef QK_SORT
	std::cout << key_size << std::endl;
#endif // QK_SORT

	// Use quick sort do the pre-sort
	_optimized_quick_sort_aux(first, last, comp, key_size);

	// Use insertion sort do the latter sort
	// Cause insertion is more effective while
	// the array is nearly sorted
	insertion_sort(first, last);
}

template <typename RandomAccessIterator, typename Compare>
void optimized_quick_sort(RandomAccessIterator first, RandomAccessIterator last, Compare comp)
{
	_optimized_quick_sort(first, last, comp, std::_Dist_type(first));
}

#endif // QUICKSORT_H

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值