// 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_