diff --git a/TinySTL/Algorithm.h b/TinySTL/Algorithm.h index c5610cc..a8df318 100644 --- a/TinySTL/Algorithm.h +++ b/TinySTL/Algorithm.h @@ -457,8 +457,7 @@ namespace TinySTL{ while (n++){ --it; } - } - else{ + }else{ while (n--){ ++it; } @@ -478,6 +477,62 @@ namespace TinySTL{ typedef iterator_traits::iterator_category iterator_category; _advance(it, n, iterator_category()); } + //********** [sort] ****************************** + //********* [Algorithm Complexity: O(NlogN)] **************** + namespace { + template + typename iterator_traits::value_type + mid3(RandomIterator first, RandomIterator last, BinaryPredicate pred){//[first, last] + auto mid = first + (last + 1 - first) / 2; + if (pred(*mid, *first)){ + swap(*mid, *first); + } + if (pred(*last, *mid)){ + swap(*last, *mid); + } + if (pred(*last, *first)){ + swap(*last, *first); + } + auto ret = *mid; + swap(*mid, *(last - 1));//将mid item换位作为哨兵 + return ret; + } + template + void bubble_sort(RandomIterator first, RandomIterator last, BinaryPredicate pred){ + auto len = last - first; + for (auto i = len; i != 0; --i){ + for (auto p = first; p != (first + i - 1); ++p){ + if (pred(*(p + 1), *p)) + swap(*(p + 1), *p); + } + } + } + } + template + void sort(RandomIterator first, RandomIterator last){ + return sort(first, last, less::value_type>()); + } + template + void sort(RandomIterator first, RandomIterator last, BinaryPredicate pred){ + static int n = 1; + if (first >= last || first + 1 == last) + return; + if (last - first <= 20)//区间长度小于等于20的采用冒泡排序更快 + return bubble_sort(first, last, pred); + auto mid = mid3(first, last - 1, pred); + auto p1 = first, p2 = last - 2; + while (p1 < p2){ + while (pred(*p1, mid) && p1 < p2) ++p1; + while (!pred(*p2, mid) && p1 < p2) --p2; + if (p1 < p2){ + swap(*p1, *p2); + } + } + swap(*p1, *(last - 2));//将作为哨兵的mid item换回原来的位置 + sort(first, p1); + sort(p1 + 1, last); + } + } diff --git a/TinySTL/Test/AlgorithmTest.cpp b/TinySTL/Test/AlgorithmTest.cpp index 79b6afd..4e3709e 100644 --- a/TinySTL/Test/AlgorithmTest.cpp +++ b/TinySTL/Test/AlgorithmTest.cpp @@ -189,6 +189,29 @@ namespace TinySTL{ TinySTL::advance(lit, -5); assert(*vit == 0 && *lit == 0); } + void testSort(){ + int arr1[1] = { 0 }; + TinySTL::sort(std::begin(arr1), std::end(arr1)); + assert(std::is_sorted(std::begin(arr1), std::end(arr1))); + + int arr2[2] = { 1, 0 }; + TinySTL::sort(std::begin(arr2), std::end(arr2)); + assert(std::is_sorted(std::begin(arr2), std::end(arr2))); + + int arr3[3] = { 2, 1, 3 }; + TinySTL::sort(std::begin(arr3), std::end(arr3)); + assert(std::is_sorted(std::begin(arr3), std::end(arr3))); + + int arr4[10000]; + std::random_device rd; + for (auto i = 0; i != 100; ++i){ + for (auto& n : arr4){ + n = rd() % 65536; + } + TinySTL::sort(std::begin(arr4), std::end(arr4)); + assert(std::is_sorted(std::begin(arr4), std::end(arr4))); + } + } void testAllCases(){ @@ -211,6 +234,7 @@ namespace TinySTL{ testIsPermutation(); testSearch(); testAdvance(); + testSort(); } } } \ No newline at end of file diff --git a/TinySTL/Test/AlgorithmTest.h b/TinySTL/Test/AlgorithmTest.h index 33c13a7..d867b31 100644 --- a/TinySTL/Test/AlgorithmTest.h +++ b/TinySTL/Test/AlgorithmTest.h @@ -11,6 +11,7 @@ #include #include #include +#include #include #include "../BinarySearchTree.h" @@ -39,6 +40,7 @@ namespace TinySTL{ void testIsPermutation(); void testSearch(); void testAdvance(); + void testSort(); void testAllCases(); }