summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/queue/queue_sort_1.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/queue/queue_sort_1.h')
-rw-r--r--ml/dlib/dlib/queue/queue_sort_1.h165
1 files changed, 165 insertions, 0 deletions
diff --git a/ml/dlib/dlib/queue/queue_sort_1.h b/ml/dlib/dlib/queue/queue_sort_1.h
new file mode 100644
index 000000000..bc20dcb82
--- /dev/null
+++ b/ml/dlib/dlib/queue/queue_sort_1.h
@@ -0,0 +1,165 @@
+// 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_
+