// Copyright (C) 2003 Davis E. King (davis@dlib.net)
// License: Boost Software License See LICENSE.txt for the full license.
#ifndef DLIB_QUEUE_SORt_1_
#define DLIB_QUEUE_SORt_1_
#include "queue_sort_abstract.h"
#include "../algs.h"
#include <vector>
#include "../sort.h"
namespace dlib
{
template <
typename queue_base
>
class queue_sort_1 : public queue_base
{
typedef typename queue_base::type T;
public:
/*!
This implementation uses the QuickSort algorithm and
when the quicksort depth goes too high it uses the dlib::qsort_array()
function on the data.
!*/
void sort (
);
template <typename compare_type>
void sort (
const compare_type& compare
)
{
if (this->size() > 1)
{
sort_this_queue(*this,0,compare);
}
}
private:
template <typename compare_type>
void sort_this_queue (
queue_base& queue,
long depth,
const compare_type& compare
)
/*!
ensures
each element in the queue is < the element behind it according
to compare
!*/
{
if (queue.size() <= 1)
{
// already sorted
}
else if (queue.size() <= 29)
{
T vect[29];
const unsigned long size = queue.size();
for (unsigned long i = 0; i < size; ++i)
{
queue.dequeue(vect[i]);
}
isort_array(vect,0,size-1,compare);
for (unsigned long i = 0; i < size; ++i)
{
queue.enqueue(vect[i]);
}
}
else if (depth > 50)
{
std::vector<T> vect(queue.size());
for (unsigned long i = 0; i < vect.size(); ++i)
{
queue.dequeue(vect[i]);
}
hsort_array(vect,0,vect.size()-1,compare);
for (unsigned long i = 0; i < vect.size(); ++i)
{
queue.enqueue(vect[i]);
}
}
else
{
queue_base left, right;
T partition_element;
T temp;
// do this just to avoid a compiler warning
assign_zero_if_built_in_scalar_type(temp);
assign_zero_if_built_in_scalar_type(partition_element);
queue.dequeue(partition_element);
// partition queue into left and right
while (queue.size() > 0)
{
queue.dequeue(temp);
if (compare(temp , partition_element))
{
left.enqueue(temp);
}
else
{
right.enqueue(temp);
}
}
long ratio;
if (left.size() > right.size())
ratio = left.size()/(right.size()+1); // add 1 so we can't divide by zero
else
ratio = right.size()/(left.size()+1);
sort_this_queue(left,ratio+depth,compare);
sort_this_queue(right,ratio+depth,compare);
// combine the two queues
left.swap(queue);
queue.enqueue(partition_element);
queue.cat(right);
}
}
};
template <
typename queue_base
>
inline void swap (
queue_sort_1<queue_base>& a,
queue_sort_1<queue_base>& b
) { a.swap(b); }
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
// member function definitions
// ----------------------------------------------------------------------------------------
// ----------------------------------------------------------------------------------------
template <
typename queue_base
>
void queue_sort_1<queue_base>::
sort (
)
{
if (this->size() > 1)
{
sort_this_queue(*this,0,std::less<typename queue_base::type>());
}
}
// ----------------------------------------------------------------------------------------
}
#endif // DLIB_QUEUE_SORt_1_