>
After applying Michael's final changes, compare the end result with your
first draft and be amazed... It calls to mind Blaise Pascal's quote:
"...my letters were not wont... to be so prolix... Want of time must
plead my excuse..."
It takes time to make code succinct.
Personally, I would have eliminated 'median', 'midPoint' as well. The
information in those variables is redundant.
The differences are crystal clear. My next step is two do some tests
with other container types and numeric types.
Thanks for the incredible information!
BTW: I kept the median/midPoint variables just for readability's sake.
I'm a verbose programmer and like things laid out and obvious because,
frankly, I don't remember much about the code I wrote last month.
Also, I don't like returning from an operator statement.
Here's my final, final, (final?) draft:
template<typename ForwardIterator>
typename std::iterator_traits<ForwardIterator>::value_type
median(ForwardIterator first, ForwardIterator last)
{
if (first == last)
throw std::domain_error("median of an empty set");
// built the temporary container big enough to do a partial sort of
one more
// of one more than half the size of the input container (odd or
even) to
// accomadate the median
typedef typename
std::iterator_traits<ForwardIterator>::difference_ type DiffType;
DiffType origSize = std::distance(first, last);
typedef typename
std::iterator_traits<ForwardIterator>::value_type ReturnType;
vector<ReturnTypetempSet((origSize + 2) / 2);
// fill in the temporary container while sorting
std::partial_sort_copy(
first,
last,
tempSet.begin(),
tempSet.end());
vector<ReturnType>::size_type midPoint = tempSet.size() - 1;
ReturnType median =
origSize % 2 == 0 ?
(tempSet[midPoint] + tempSet[midPoint - 1]) / 2 :
tempSet[midPoint];
return median;
}