Simple Application Framework
1
|
00001 /* 00002 This file is part of Simple Application Framework (Saf) library. 00003 Copyright (C) 2010 - 2012 Ondrej Danek <ondrej.danek@gmail.com> 00004 00005 This library is free software: you can redistribute it and/or modify 00006 it under the terms of the GNU General Public License as published 00007 by the Free Software Foundation, either version 3 of the License, or 00008 (at your option) any later version. 00009 00010 Saf is distributed in the hope that it will be useful, 00011 but WITHOUT ANY WARRANTY; without even the implied warranty of 00012 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 00013 GNU General Public License for more details. 00014 00015 You should have received a copy of the GNU General Public License 00016 along with Simple Application Framework library. If not, 00017 see <http://www.gnu.org/licenses/>. 00018 */ 00019 00028 #ifndef SAF_ALGO_SORT_INTROSORT_H 00029 #define SAF_ALGO_SORT_INTROSORT_H 00030 00031 #include "../../Type.h" 00032 #include "../Predicate.h" 00033 #include "../../Math/Calculus/Powers.h" 00034 #include "../../Collection/Pair.h" 00035 #include "HeapSort.h" 00036 #include "InsertionSort.h" 00037 #include "SortInternal.h" 00038 00039 namespace Saf 00040 { 00042 namespace Internal 00043 { 00044 namespace AlgoSort 00045 { 00047 const Saf::Diff IntroSortInsertionLimit = 32; 00048 00050 template <class RanIter, class Pred> 00051 void IntroSort(RanIter begin, RanIter end, Pred pred, Saf::Size depthLimit) 00052 { 00053 while (Saf::Diff(end - begin) > IntroSortInsertionLimit && depthLimit > 0) 00054 { 00055 --depthLimit; 00056 00057 // Find pivot and partition the sequence into two parts 00058 Saf::Collection::Pair<RanIter,RanIter> cut; 00059 cut = Internal::AlgoSort::PartitionSmart(begin, end, pred); 00060 00061 // No need to proceed with the shorter sequence due to the 00062 // logarithmic recursion bound given by depthLimit. 00063 IntroSort(cut.m_second, end, pred, depthLimit); 00064 end = cut.m_first; 00065 } 00066 00067 if (Saf::Diff(end - begin) > IntroSortInsertionLimit) 00068 { 00069 // Too many recursions, use heap sort to sort the rest 00070 Saf::Algo::Sort::HeapSort(begin, end, pred); 00071 } 00072 else 00073 { 00074 // Short sequence, use cache friendly insertion sort 00075 Saf::Algo::Sort::InsertionSort(begin, end, pred); 00076 } 00077 } 00078 } 00079 } 00082 namespace Algo 00083 { 00084 namespace Sort 00085 { 00105 template <class RanIter, class Pred> 00106 void IntroSort(RanIter begin, RanIter end, Pred pred) 00107 { 00108 Diff len = end - begin; 00109 00110 if (len > 1) 00111 { 00112 // Set the depth limit to 1.5 * log2(n) 00113 Size depthLimit = 3 * Math::Calculus::BinaryLogarithm(Size(len)) / 2; 00114 00115 // Quicksort + insertion sort with a heap sort fallback 00116 Internal::AlgoSort::IntroSort(begin, end, pred, depthLimit); 00117 } 00118 } 00119 00138 template <class RanIter> 00139 void IntroSort(RanIter begin, RanIter end) 00140 { 00141 Predicate::Less<typename Type::IteratorTraits<RanIter>::ValType> pred; 00142 IntroSort(begin, end, pred); 00143 } 00144 } 00145 } 00146 } 00147 00148 #endif