// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_SEQUENCE_SORt_1_
#define DLIB_SEQUENCE_SORt_1_
#include "sequence_sort_abstract.h"
#include "../algs.h"
namespace dlib
{
template <
typename seq_base
>
class sequence_sort_1 : public seq_base
{
typedef typename seq_base::type T;
public:
/*!
this is a median of three version of the QuickSort algorithm and
it sorts sequences of less than 30 elements with a selection sort
!*/
void sort (
);
private:
void sort_this_sequence (
seq_base& sequence
);
/*!
ensures
- each element in the sequence is < the element behind it
!*/
void selection_sort (
seq_base& sequence
);
/*!
ensures
- sequence is sorted with a selection_sort
!*/
};
template <
typename seq_base
>
inline void swap (
sequence_sort_1<seq_base>& a,
sequence_sort_1<seq_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename seq_base
>
void sequence_sort_1<seq_base>::
sort (
)
{
if (this->size() > 1)
{
sort_this_sequence(*this);
}
}
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// private member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename seq_base
>
void sequence_sort_1<seq_base>::
sort_this_sequence (
seq_base& sequence
)
{
if (sequence.size() < 30)
{
selection_sort(sequence);
}
else
{
seq_base left, right;
T partition_element;
sequence.remove(0,partition_element);
dlib::median (
partition_element,
sequence[sequence.size()-1],
sequence[(sequence.size()-1)/2]
);
// partition sequence into left and right
T temp;
while (sequence.size() > 0)
{
sequence.remove(0,temp);
if (temp < partition_element)
{
left.add(0,temp);
}
else
{
right.add(0,temp);
}
}
sort_this_sequence(left);
sort_this_sequence(right);
// combine left and right into sequence
left.swap(sequence);
sequence.add(sequence.size(),partition_element);
sequence.cat(right);
}
}
// ----------------------------------------------------------------------------------------
template <
typename seq_base
>
void sequence_sort_1<seq_base>::
selection_sort (
seq_base& sequence
)
{
if (sequence.size() > 2)
{
T temp[29];
unsigned long ssize = sequence.size();
for (unsigned long i = 0; i < ssize; ++i)
sequence.remove(0,temp[i]);
unsigned long smallest;
for (unsigned long i = 0; i < ssize - 1; ++i)
{
// find smallest element and swap into i
smallest = i;
for (unsigned long j = i+1; j < ssize; ++j)
{
if (temp[j] < temp[smallest])
smallest = j;
}
exchange(temp[smallest],temp[i]);
}
for (unsigned long i = 0; i < ssize; ++i)
sequence.add(i,temp[i]);
}
else if (sequence.size() == 2)
{
if (sequence[1] < sequence[0])
{
exchange(sequence[0],sequence[1]);
}
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_SEQUENCE_SORt_1_