By posting articles on the STL Chinese site, I feel that I cannot find the address when I want to refer to it and simply post it to my blog.
STL sorting (SORT)
Author winter
- STL sorting (SORT)
- Why do you have to master STL?
- 1. Sort Algorithm provided by STL
- 1.1 Introduction to all sort Algorithms
- 1.2 comparison functions in sort
- 1.3 sort Stability
- 1.4 full sorting
- 1.5 partial sorting
- 1.6 nth_element specifies the sorting of Elements
- 1.7 partition and stable_partition
- 2 sort and container
- 3. select an appropriate sorting Function
- 4. Summary
- 5 References
All complex sorting operations can be easily implemented through STL!
Why do you have to master STL?
For programmers, data structure is a required course. From searching to sorting, from linked list to binary tree, almost all algorithms and principles need to be understood. If you cannot understand them, you must memorize them. Fortunately, these theories are mature and the algorithms are basically fixed. You don't have to worry about the algorithm principles or verify the accuracy. However, when you start to use computer languages to work, you will find that you need to repeat these mature algorithms with code again and again in the face of different needs, in addition, it will fall into some bugs due to negligence again and again. At this time, you want to find a tool that has helped you implement these functions. You can use it whenever you want, without affecting performance. What you need is STL, a standard template library!
There is a saying in the West: Do not reinvent the wheel!
STL encapsulates almost all algorithms in the data structure, from linked list to queue, from vector to stack, to hash to binary tree, from search to sorting, from adding to deleting ...... it can be said that if you understand STL, you will find that you do not have to stick to the algorithm itself, so that you can stand on the shoulders of giants to consider more advanced applications.
Sorting is one of the most widely used algorithms. This article describes the usage and differences of different sorting algorithms in STL.
1. Sort Algorithm provided by STL
The reason why C ++ is liked by so many people is that it has both the object-oriented concept and the high efficiency of C language. STL sorting algorithms also need to be efficient. Therefore, STL provides different functions and functions for different requirements, and the implemented algorithms are different.
1.1 Introduction to all sort Algorithms
All sort algorithm parameters must enter a range, [begin, end ). The iterator used here must be a radomaccessiterator, that is, an iterator that can be accessed randomly, such as IT + N. (Except for partition and stable_partition)
If you need to define a comparison function, you can pass in the defined function as a parameter. Each algorithm supports the input of comparison functions. The following lists the names of all STL Sort Algorithm functions:
Function Name |
Function Description |
Sort |
Sorts all elements in a given range. |
Stable_sort |
Performs a stable sorting of all elements in a given range. |
Partial_sort |
Sorts all elements in a given range. |
Partial_sort_copy |
Copy and sort a given interval |
Nth_element |
Find the elements corresponding to a location in a given range |
Is_sorted |
Determine whether the order of an interval has been sorted |
Partition |
Place elements that meet certain conditions in front of them. |
Stable_partition |
Relatively stable putting elements that meet certain conditions in front |
Among them, nth_element is the least understandable. In fact, this function is used to find the first few. For example, find out the value of the number in the middle of the array containing seven elements. At this time, I may not care about the front or the back. I only care about the value of the fourth element.
1.2 comparison functions in sort
When you need to sort by a specific method, you need to specify a comparison function for sort, otherwise the program will automatically provide you with a comparison function.
Vector <int> vect ;//... sort (vect. begin (), vect. end (); // call sort (vect. begin (), vect. end (), less <int> ());
In the preceding example, the system provides the less function for sort. Other functions are also provided in STL. The following is a list of functions:
Name |
Function Description |
Performance_to |
Equal |
Not_0000_to |
Not equal |
Less |
Less |
Greater |
Greater |
Less_equal |
Less than or equal |
Greater_equal |
Greater than or equal |
It should be noted that these functions are not applicable to your sort algorithm. How to choose them depends on your application. In addition, you cannot directly write the name of the imitation function. Instead, you need to write its overloaded () function:
less<int>()greater<int>()
When elements in your container are of some standard type (INT float char) or string, you can directly use these function templates. However, if you define your own types or you need to sort them by other means, you can use either of the following methods to achieve the effect: Write A comparison function by yourself. The other is the '<' operation of the overload type.
#include <iostream>#include <algorithm>#include <functional>#include <vector>using namespace std;class myclass { public: myclass(int a, int b):first(a), second(b){} int first; int second; bool operator < (const myclass &m)const { return first < m.first; }};bool less_second(const myclass & m1, const myclass & m2) { return m1.second < m2.second;}int main() { vector< myclass > vect; for(int i = 0 ; i < 10 ; i ++){ myclass my(10-i, i*3); vect.push_back(my); } for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; sort(vect.begin(), vect.end()); cout<<"after sorted by first:"<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; cout<<"after sorted by second:"<<endl; sort(vect.begin(), vect.end(), less_second); for(int i = 0 ; i < vect.size(); i ++) cout<<"("<<vect[i].first<<","<<vect[i].second<<")/n"; return 0 ;}
Know what the output result is:
(10,0)(9,3)(8,6)(7,9)(6,12)(5,15)(4,18)(3,21)(2,24)(1,27)after sorted by first:(1,27)(2,24)(3,21)(4,18)(5,15)(6,12)(7,9)(8,6)(9,3)(10,0)after sorted by second:(10,0)(9,3)(8,6)(7,9)(6,12)(5,15)(4,18)(3,21)(2,24)(1,27)
1.3 sort StabilityYou may find sort and stable_sort, partition, and stable_partition strange. The difference is that functions with stable can ensure that the original relative order of equal elements remains unchanged after sorting. Maybe you will ask, since they are equal, you still care about their relative positions, and you cannot tell who they are? Here we need to clarify a problem. The equality here means that the two elements are equal and not necessarily the same element.
For example, if you write a comparison function:
bool less_len(const string &str1, const string &str2){ return str1.length() < str2.length();}
At this time, "apple" and "Winter" are equal. If "apple" appears before "Winter", their order will remain unchanged after being sorted by functions with stable, if you are using a function without "stable", "Winter" may be before "apple" after sorting.
1.4 full sortingIn full order, all elements in a given range are arranged in order of size and relationship. Functions used for full sorting include:
template <class RandomAccessIterator>void sort(RandomAccessIterator first, RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void sort(RandomAccessIterator first, RandomAccessIterator last,StrictWeakOrdering comp);template <class RandomAccessIterator>void stable_sort(RandomAccessIterator first, RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void stable_sort(RandomAccessIterator first, RandomAccessIterator last, StrictWeakOrdering comp);
In the 1 and 3 forms, neither sort nor stable_sort specify a comparison function. By default, the system uses operator <to sort all elements in the interval [first, last). Therefore, if the type yejun you are using has reloaded the operator function, you can worry about it. You can specify comparison functions at will in four forms: 2nd and, so that applications are more flexible. Let's take a look at the actual application:
There are 10 students in the class. I want to know their ranking.
#include <iostream>#include <algorithm>#include <functional>#include <vector>#include <string>using namespace std;class student{ public: student(const string &a, int b):name(a), score(b){} string name; int score; bool operator < (const student &m)const { return score< m.score; }};int main() { vector< student> vect; student st1("Tom", 74); vect.push_back(st1); st1.name="Jimy"; st1.score=56; vect.push_back(st1); st1.name="Mary"; st1.score=92; vect.push_back(st1); st1.name="Jessy"; st1.score=85; vect.push_back(st1); st1.name="Jone"; st1.score=56; vect.push_back(st1); st1.name="Bush"; st1.score=52; vect.push_back(st1); st1.name="Winter"; st1.score=77; vect.push_back(st1); st1.name="Andyer"; st1.score=63; vect.push_back(st1); st1.name="Lily"; st1.score=76; vect.push_back(st1); st1.name="Maryia"; st1.score=89; vect.push_back(st1); cout<<"------before sort..."<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<vect[i].name<<":/t"<<vect[i].score<<endl; stable_sort(vect.begin(), vect.end(),less<student>()); cout <<"-----after sort ...."<<endl; for(int i = 0 ; i < vect.size(); i ++) cout<<vect[i].name<<":/t"<<vect[i].score<<endl; return 0 ;}
The output is:
------before sort...Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52Winter: 77Andyer: 63Lily: 76Maryia: 89-----after sort ....Bush: 52Jimy: 56Jone: 56Andyer: 63Tom: 74Lily: 76Winter: 77Jessy: 85Maryia: 89Mary: 92
Sort uses a mature "quick sorting algorithm" (currently, most STL versions do not adopt simple quick sorting, but use interpolation sorting algorithms ). Note 1: the average performance and complexity can be ensured to be n * log (N). Due to the worst case in theory in simple fast sorting, the performance is very low, the algorithm complexity is N * n, but most STL versions have been optimized in this aspect, so you can safely use it. Stable_sort uses "Merge Sorting". If enough memory is allocated, the algorithm complexity is N * log (N). Otherwise, the complexity is N * log (n) * log (n) has the advantage that the relative positions of equal elements are consistent before and after sorting.
1.5 partial sortingPartial sorting is actually a sort method provided to reduce unnecessary operations. Its function prototype is:
template <class RandomAccessIterator>void partial_sort(RandomAccessIterator first, RandomAccessIterator middle,RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void partial_sort(RandomAccessIterator first,RandomAccessIterator middle,RandomAccessIterator last, StrictWeakOrdering comp);template <class InputIterator, class RandomAccessIterator>RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last,RandomAccessIterator result_first,RandomAccessIterator result_last);template <class InputIterator, class RandomAccessIterator, class StrictWeakOrdering>RandomAccessIterator partial_sort_copy(InputIterator first, InputIterator last,RandomAccessIterator result_first,RandomAccessIterator result_last, Compare comp);
After understanding sort and stable_sort, it is easier to understand partial_sort. Let's take a look at its purpose: there are 10 students in the class. I want to know who has the lowest scores. If there is no partial_sort, you need to use sort to sort all people in order and then take the first five. Now you only need to sort the lowest scores by 5 and modify the above program as follows:
Stable_sort (vect. begin (), vect. end (), less <student> (); replace with: partial_sort (vect. begin (), vect. begin () + 5, vect. end (), less <student> ());
Output result:
------before sort...Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52Winter: 77Andyer: 63Lily: 76Maryia: 89-----after sort ....Bush: 52Jimy: 56Jone: 56Andyer: 63Tom: 74Mary: 92Jessy: 85Winter: 77Lily: 76Maryia: 89
Do you know the benefits? When the data size is small, it may not be able to see the advantage. If it is 1 million students, I want to find the minimum score of 5 people ......
The heapsort used by partial_sort, whose complexity is N * log (n) in any situation ). if you want to use partial_sort for full sorting, you only need to make middle = last.
Partial_sort_copy is a combination of copy and partial_sort. The number of sorted (replicated) values is the one with a smaller interval in [first, last) and [result_first, result_last. If the [result_first, result_last) interval is greater than the [first, last) interval, partial_sort is equivalent to a combination of copy and sort.
1.6 nth_element specifies the sorting of ElementsNth_element is a sort that is easy to understand but difficult to explain. The example is more convenient:
There are 10 students in the class. I want to know the number of students with the lowest scores.
If you want to meet the above requirements, you can use sort to sort the order, and then take the 4th bits (because it is from small to large). More intelligent friends will use partial_sort to rank only the first four bits, then we get 4th bits. In fact, this is a waste, because you do not need to sort the first two. In this case, you need nth_element:
template <class RandomAccessIterator>void nth_element(RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last);template <class RandomAccessIterator, class StrictWeakOrdering>void nth_element(RandomAccessIterator first, RandomAccessIterator nth,RandomAccessIterator last, StrictWeakOrdering comp);
For the above instance requirements, you only need to modify the program in 1.4 as follows:
Stable_sort (vect. begin (), vect. end (), less <student> (); replace with: nth_element (vect. begin (), vect. begin () + 3, vect. end (), less <student> ());
The running result is:
------before sort...Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52Winter: 77Andyer: 63Lily: 76Maryia: 89-----after sort ....Jone: 56Bush: 52Jimy: 56Andyer: 63Jessy: 85Mary: 92Winter: 77Tom: 74Lily: 76Maryia: 89
Who is the fourth? Andyer, this unlucky guy. Why is it begin () + 3 instead of + 4? I did not care when I started writing this article. Later I found this problem with the reminder of ilovevc. Begin () is the first, begin () + 1 is the second, and... begin () + 3 is of course the fourth.
1.7 partition and stable_partitionIt seems that these two functions are not used for sorting. The 'category' algorithm will be more appropriate. Partition divides the elements in a range into two types according to a certain condition. Its function prototype is:
template <class ForwardIterator, class Predicate>ForwardIterator partition(ForwardIterator first,ForwardIterator last, Predicate pred)template <class ForwardIterator, class Predicate>ForwardIterator stable_partition(ForwardIterator first, ForwardIterator last, Predicate pred);
Let's take a look at the application: there are 10 students in the class who have passed the calculation (below 60 points. You only need to replace the program 1.4 in the following format:
Stable_sort (vect. begin (), vect. end (), less <student> (); replace with: student exam ("pass", 60); stable_partition (vect. begin (), vect. end (), bind2nd (less <student> (), exam ));
The output result is:
------before sort...Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52Winter: 77Andyer: 63Lily: 76Maryia: 89-----after sort ....Jimy: 56Jone: 56Bush: 52Tom: 74Mary: 92Jessy: 85Winter: 77Andyer: 63Lily: 76Maryia: 89
Have you seen it? jimy, Jone, and Bush (no wonder the US president is stupid) fail. In addition, stable_partition is used, and the relative order between elements is not changed.
2 sort and container
In STL, the standard containers mainly include vector, list, deque, String, set, Multiset, map, and multimay, where set, Multiset, map, multimap stores all its elements in a tree structure. For details, refer to: Learning STL map and STL set as the data structure basis. therefore, elements in these containers are always ordered.
The iterator types of these containers are not random iterators. Therefore, the sorting functions described above are unavailable for these containers. The above sort function is available for the following containers:
If the container you define also supports the random iterator, there is no problem in using the sorting algorithm.
For the list container, list comes with an sort member function list: Sort (). it is similar to sort in Algorithm functions, but list: sort is sorted Based on pointers. That is to say, all data movement and comparison are implemented using pointers, therefore, the sorted iterator remains valid (the iterator after sort in the vector will become invalid ).
3. select an appropriate sorting Function
Why should we select a proper sorting function? Maybe you don't care about efficiency (the efficiency here refers to the program running time), or you have a small amount of data, so you don't think any function is important.
Otherwise, even if you don't care about efficiency, if you choose a proper sorting function, you will make your code easier to understand, and you will make your code more scalable, it is very important to gradually develop a good habit.
If you have used qsort in C language before and want to know the comparison between qsort and them, I will tell you that qsort and sort are the same, because they adopt fast sorting. In terms of efficiency, the following sort algorithms provide a sorting algorithm, with the efficiency increasing from high to low (the time consumed increases from small to large ):
- Partion
- Stable_partition
- Nth_element
- Partial_sort
- Sort
- Stable_sort
Remember, I have translated the article about objective STL before, which summarizes how to select a sort function:
- To sort the vector, String, deque, or array containers in full order, you can select sort or stable_sort;
- If you only need to obtain the top n elements in the vector, String, deque, or array container, partial_sort is the first choice.
- For a vector, String, deque, or array container, you need to find the element at the nth position or you need to get the top N and it is not related to the internal order in Top N, nth_element is the most ideal;
- If you want to separate elements that meet or do not meet a certain condition from the standard sequence container or array, you 'd better use partition or stable_partition;
- If you use the list container, you can directly use the partition and stable_partition algorithms. You can use list: sort to replace sort and stable_sort to sort. If you want to obtain the sorting effect of partial_sort or nth_element, you must use it indirectly. As described above, you can choose from several methods.
Remember one sentence:If you want to save time, do not make detours, or take extra steps!
4. Summary
The discussion of technology is like a bottomless pit, and it is often easy to extend from one point to countless other technical points. Therefore, we need to observe the problem from a global perspective, just like the sort algorithm in STL. In fact, there are also sorting algorithms such as make_heap and sort_heap in STL. This article does not mention. This article explains the characteristics of sorting algorithms in STL using examples, and summarizes how to select appropriate algorithms in actual situations.
5 References
Clause 31: How to Select a sort function
The standard librarian: Sorting in the standard library
Simplified STL Chinese Version
Standard Template Library programmer's Guide