summaryrefslogtreecommitdiffstats
path: root/ml/dlib/dlib/sort.h
diff options
context:
space:
mode:
Diffstat (limited to 'ml/dlib/dlib/sort.h')
-rw-r--r--ml/dlib/dlib/sort.h490
1 files changed, 490 insertions, 0 deletions
diff --git a/ml/dlib/dlib/sort.h b/ml/dlib/dlib/sort.h
new file mode 100644
index 000000000..c798372f3
--- /dev/null
+++ b/ml/dlib/dlib/sort.h
@@ -0,0 +1,490 @@
+// Copyright (C) 2005 Davis E. King (davis@dlib.net)
+// License: Boost Software License See LICENSE.txt for the full license.
+#ifndef DLIB_SORt_
+#define DLIB_SORt_
+
+#include "algs.h"
+#include <functional>
+
+namespace dlib
+{
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ inline void qsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right,
+ const compare& comp
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by comp where comp is a function
+ object with the same syntax as std::less<>
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using a quick sort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void hsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right,
+ const compare& comp
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by comp where comp is a function
+ object with the same syntax as std::less<>
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using a heapsort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void isort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right,
+ const compare& comp
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by comp where comp is a function
+ object with the same syntax as std::less<>
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using an insertion sort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T
+ >
+ inline void qsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by std::less
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using a quick sort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T
+ >
+ void hsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by std::less
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using a heapsort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T
+ >
+ void isort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ );
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by std::less
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ - left <= right
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - sorts using an insertion sort algorithm
+ !*/
+
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+// IMPLEMENTATION DETAILS
+// ----------------------------------------------------------------------------------------
+// ----------------------------------------------------------------------------------------
+
+ namespace sort_helpers
+ {
+ template <typename T>
+ inline const std::less<T> comp (const T&)
+ {
+ return std::less<T>();
+ }
+
+ template <
+ typename T,
+ typename Y,
+ typename compare
+ >
+ inline unsigned long qsort_partition (
+ T& array,
+ Y& pivot,
+ const unsigned long left,
+ const unsigned long right,
+ const compare& comp
+ )
+ /*!
+ requires
+ - &pivot == &array[right]
+ - T implements operator[]
+ - the items in array must be comparable by comp
+ - left and right are within the bounts of the array
+ - left < right
+ ensures
+ - returns a number called partition_element such that:
+ - left <= partition_element <= right
+ - all elements in #array < #array[partition_element] have
+ indices >= left and < partition_element
+ - all elements in #array > #array[partition_element] have
+ indices > partition_element and <= right
+ !*/
+ {
+ DLIB_ASSERT (&pivot == &array[right] && left < right,
+ "\tunsigned long qsort_partition()"
+ << "\n\t&pivot: " << &pivot
+ << "\n\t&array[right]: " << &array[right]
+ << "\n\tleft: " << left
+ << "\n\tright: " << right );
+
+ exchange(array[(right-left)/2 +left],pivot);
+
+ unsigned long i = left;
+ for (unsigned long j = left; j < right; ++j)
+ {
+ if (comp(array[j] , pivot))
+ {
+ swap(array[i],array[j]);
+ ++i;
+ }
+ }
+ exchange(array[i],pivot);
+
+ return i;
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void qsort_array_main (
+ T& array,
+ const unsigned long left,
+ const unsigned long right,
+ unsigned long depth_check,
+ const compare& comp
+ )
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by comp
+ - the items in array must be swappable by a global swap()
+ - left and right are within the bounds of array
+ i.e. array[left] and array[right] are valid elements
+ ensures
+ - for all elements in #array between and including left and right the
+ ith element is < the i+1 element
+ - will only recurse about as deep as log(depth_check) calls
+ - sorts using a quick sort algorithm
+ !*/
+ {
+ if ( left < right)
+ {
+ if (right-left < 30 || depth_check == 0)
+ {
+ hsort_array(array,left,right,comp);
+ }
+ else
+ {
+ // The idea here is to only let quick sort go about log(N)
+ // calls deep before it kicks into something else.
+ depth_check >>= 1;
+ depth_check += (depth_check>>4);
+
+ unsigned long partition_element =
+ qsort_partition(array,array[right],left,right,comp);
+
+ if (partition_element > 0)
+ qsort_array_main(array,left,partition_element-1,depth_check,comp);
+ qsort_array_main(array,partition_element+1,right,depth_check,comp);
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void heapify (
+ T& array,
+ const unsigned long start,
+ const unsigned long end,
+ unsigned long i,
+ const compare& comp
+ )
+ /*!
+ requires
+ - T implements operator[]
+ - the items in array must be comparable by comp
+ - the items in array must be swappable by a global swap()
+ - start, end, and i are within the bounds of array
+ i.e. array[start], array[end], and array[i] are valid elements
+ - start <= i <= end
+ - array[i/2] is a max heap
+ - array[i/2+1] is a max heap
+ - start and end specify the range of the array we are working with.
+ ensures
+ - array[i] is now a max heap
+ !*/
+ {
+ DLIB_ASSERT (start <= i && i <= end,
+ "\tvoid heapify()"
+ << "\n\tstart: " << start
+ << "\n\tend: " << end
+ << "\n\ti: " << i );
+
+ bool keep_going = true;
+ unsigned long left;
+ unsigned long right;
+ unsigned long largest;
+ while (keep_going)
+ {
+ keep_going = false;
+ left = (i<<1)+1-start;
+ right = left+1;
+
+ if (left <= end && comp(array[i] , array[left]))
+ largest = left;
+ else
+ largest = i;
+
+ if (right <= end && comp(array[largest] , array[right]))
+ largest = right;
+
+ if (largest != i)
+ {
+ exchange(array[i],array[largest]);
+ i = largest;
+ keep_going = true;
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+ }
+// ----------------------------------------------------------------------------------------
+
+
+ template <
+ typename T
+ >
+ inline void qsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ )
+ {
+ using namespace sort_helpers;
+ qsort_array(array,left,right,comp(array[left]));
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T
+ >
+ void hsort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ )
+ {
+ using namespace sort_helpers;
+ hsort_array(array,left,right,comp(array[left]));
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T
+ >
+ void isort_array (
+ T& array,
+ unsigned long left,
+ unsigned long right
+ )
+ {
+ using namespace sort_helpers;
+ isort_array(array,left,right,comp(array[left]));
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void isort_array (
+ T& array,
+ const unsigned long left,
+ const unsigned long right,
+ const compare& comp
+ )
+ {
+ DLIB_ASSERT (left <= right,
+ "\tvoid isort_array()"
+ << "\n\tleft: " << left
+ << "\n\tright: " << right );
+ using namespace sort_helpers;
+
+ unsigned long pos;
+ for (unsigned long i = left+1; i <= right; ++i)
+ {
+ // everything from left to i-1 is sorted.
+ pos = i;
+ for (unsigned long j = i-1; comp(array[pos] , array[j]); --j)
+ {
+ exchange(array[pos],array[j]);
+ pos = j;
+
+ if (j == left)
+ break;
+ }
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void qsort_array (
+ T& array,
+ const unsigned long left,
+ const unsigned long right,
+ const compare& comp
+ )
+ {
+ DLIB_ASSERT (left <= right,
+ "\tvoid qsort_array()"
+ << "\n\tleft: " << left
+ << "\n\tright: " << right );
+
+ sort_helpers::qsort_array_main(array,left,right,right-left,comp);
+ }
+
+// ----------------------------------------------------------------------------------------
+
+ template <
+ typename T,
+ typename compare
+ >
+ void hsort_array (
+ T& array,
+ const unsigned long left,
+ const unsigned long right,
+ const compare& comp
+ )
+ {
+ DLIB_ASSERT (left <= right,
+ "\tvoid hsort_array()"
+ << "\n\tleft: " << left
+ << "\n\tright: " << right );
+
+ if (right-left < 30)
+ {
+ isort_array(array,left,right,comp);
+ return;
+ }
+
+ // turn array into a max heap
+ for (unsigned long i = left+((right-left)>>1);; --i)
+ {
+ sort_helpers::heapify(array,left,right,i,comp);
+ if (i == left)
+ break;
+ }
+
+ // now sort the array
+ for (unsigned long i = right; i > left;)
+ {
+ exchange(array[i],array[left]);
+ sort_helpers::heapify(array,left,--i,left,comp);
+ }
+ }
+
+// ----------------------------------------------------------------------------------------
+
+}
+
+#endif // DLIB_SORt_
+