Sort

*all complex sorting operations, can be easily implemented through the STL* !

0 Preface: STL, why do you have to master

For programmers, data structures are a compulsory subject. From the search to the sort, from the list to the two fork tree, almost all algorithms and principles need to understand, can not understand also to memorize. Fortunately, these theories have been more mature, the algorithm is also basically fixed, do not need to spend your mind to consider the principle of its algorithm, and no longer to verify its accuracy. However, when you start using computer language to work, you will find that in the face of different needs, you need to repeat these mature algorithms over and over again, and again and again into some of the bugs caused by their own negligence. At this point, you want to find a tool that has helped you achieve these functions, you can use them as much as you want, without affecting performance. What you need is STL, Standard Template Library!

There is a saying in the West: Don't invent the wheel again!

The STL encapsulates almost all the algorithms in the data structure, from the list to the queue, from the vector to the stack, to the hash to the two-fork tree, from the search to the sorting, from the add to the deletion ... It can be said that if you understand the STL, you will find that you do not have to adhere to the algorithm itself, so standing on the shoulders of giants to consider more advanced applications.

Sorting is one of the most widely used algorithms, this paper introduces in detail the usage and difference of different sorting algorithms in STL.

1 the sort algorithm provided by STL

C + + has been so many people like, because it has an object-oriented concept, but also maintain the high efficiency of C language features. The STL sorting algorithm also needs to be kept efficient. Therefore, for different needs, the STL provides different functions, different functions, the implementation of the algorithm is not the same.

1.1 Introduction to all sort algorithms

All the sort algorithm parameters need to be entered in a range, [begin, end]. The iterator (iterator) used here needs to be a random iterator (radomaccessiterator), that is, an iterator that can be randomly accessed, such as: It+n or something. (except partition and stable_partition)

If you need to define a comparison function yourself, you can pass the functor you have defined as a parameter. Each of these algorithms supports incoming comparison functions. The following is the list of names for all STL sort algorithm functions:

The name of the function |
Function Description |

Sort |
Sort all the elements of a given interval |

Stable_sort |
Stable ordering of all elements in a given interval |

Partial_sort |
Sort all elements in a given interval |

Partial_sort_copy |
Copy and sort for a given interval |

Nth_element |
Find the element that corresponds to a position in a given interval |

is_sorted |
To determine whether an interval has been ordered. |

Partition |
Make elements that meet a certain condition in the front |

Stable_partition |
A relatively stable element in front of which a condition is met |

Where Nth_element is the most difficult to understand, in fact, this function is used to find the first few. For example, to find the value of the number in the middle of an array that contains 7 elements, I may not care about the front or the back, and I only care about the value of the element in the fourth position.

Comparison functions in the 1.2 sort

When you need to sort in a particular way, you need to specify a comparison function for sort, or the program will automatically provide you with a comparison function.

int > Vect; //... Sort (Vect.begin (), Vect.end ()); //This is equivalent to calling sort (vect.begin (), Vect.end (), less<int> ());

In the example above, the system itself provides a less imitation function for sort. Other affine functions are also available in the STL, and the following is a list of affine functions:

name |
Function Description |

Equal_to |
Equal |

Not_equal_to |
Not equal |

Less |
Less than |

Greater |
Greater than |

Less_equal |
Less than or equal to |

Greater_equal |
Greater than or equal to |

It should be noted that these functions are not all applicable to your sort algorithm, and how you choose it depends on your application. In addition, you cannot write the name of an imitation function directly, but rather write its overloaded () function:

Less<int> () greater<int> ()

You can use these function templates directly when elements in your container are of standard type (int float char) or string. But if you define your own type or you need to sort by other means, there are two ways you can achieve the effect: one is to write the comparison function yourself. The other is an overloaded type of ' < ' operator assignment.

#include<iostream>#include<algorithm>#include<functional>#include<vector>using namespaceStdclassMyClass { Public: MyClass (intAintb): (a), second (b) {}intFirstintSecondBOOL operator< (ConstMyClass &m)Const{ return< M.first; }};BOOLLess_second (ConstMyClass & M1,ConstMyClass & m2) { returnM1.second < M2.second;}intMain () {vector< MyClass > Vect; for(inti = 0; I < 10; i + +) {MyClass my (10-i, i*3); Vect.push_back (my); } for(inti = 0; I < vect.size (); i + +) cout<< "("<<vect[i].first<<","<<vect[i].second<<") \ n"; Sort (Vect.begin (), Vect.end ()); cout<< "After sorted by:"<<endl; for(inti = 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(inti = 0; I < vect.size (); i + +) cout<< "("<<vect[i].first<<","<<vect[i].second<<") \ n"; return0;}

Know what the output is:

(10,0) (9,3) (8,6) (7,9) (6,12) (5,15) (4,18) (3,21) (2,24) (1,27) after sorted by-a (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)

Stability of 1.3 sort

You find that sort and stable_sort, and partition and Stable_partition, are surprised. The difference is that a function with stable guarantees that the original relative order of the equal elements remains unchanged after the order is sorted. Perhaps you will ask, since the equal, you also control him relative position, also don't know who is who? There's a problem here, and the equivalence here is that the function you provide means that two elements are equal, not necessarily the same element.

For example, if you write a comparison function:

bool Less_len (constconst string &str2) {return str1.length () < Str2.length ();}

At this point, "Apple" and "winter" is equal, if the "Apple" appears in front of the "winter", with the stable function sorted, their order must be unchanged, if you are using a function without "stable" sort, then after sorting, " Winter "is probably in front of Apple."

1.4 Full Order

A full order arranges all elements of a given range in the order of size relationships. The functions used for full sorting are

Template <class randomaccessiterator>void sort (randomaccessiterator, Randomaccessiterator last); Template <classclass strictweakordering>void sort (randomaccessiterator The randomaccessiterator last,strictweakordering comp); Template <class randomaccessiterator>void stable_sort (Randomaccessiterator, Randomaccessiterator last); Template <classclass strictweakordering>void Stable_sort ( Randomaccessiterator, Randomaccessiterator last, strictweakordering comp);

In the 1th, 3 forms, sort and stable_sort do not specify a comparison function, the system defaults to using operator< to sort all the elements within the interval [first,last), so if you use a type of rebel that has overloaded the operator < function, then you can worry about it. 2nd, 4 forms, you can specify the comparison function at will, the application is more flexible. Take a look at the actual application:

There are 10 students in the class, I want to know their grades.

#include<iostream>#include<algorithm>#include<functional>#include<vector>#include<string>using namespaceStdclassstudent{ Public: Student (ConstString &a,intb): Name (a), score (b) {} string name;intScoreBOOL operator< (ConstStudent &m)Const{ returnscore< M.score; }};intMain () {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(inti = 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(inti = 0; I < vect.size (); i + +) cout<<vect[i].name<< ": \ t"<<vect[i].score<<endl; return0;}

Its output is:

------before sort ... Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52winter:77andyer:63lily: 76Maryia: | -----after sort .... Bush: 52Jimy: 56Jone: 56andyer:63tom: 74Lily: 76winter:77jessy: 85maryia:89mary: 92

Sort is a mature "fast sorting algorithm" (most of the current version of STL is not a simple quick sort, but a combination of interpolation sorting algorithm).

__Note 1__, you can guarantee a good average performance, complexity is N*log (n), because the simple fast sort in theory has the worst, the performance is very low, its algorithm complexity is n*n, but most of the STL version has been done in this aspect of optimization, so you can be assured to use. Stable_sort uses the "merge sort", allocates enough memory is, its algorithm complexity is N*log (n), otherwise its complexity is N*log (n) *log (n), its advantage is to maintain the relative position between equal elements before and after the order is consistent.

1.5 Local sort

Local sorting is actually a sort of ordering that is provided to reduce unnecessary operations. Its function prototype is:

Template<classRandomaccessiterator>voidPartial_sort (Randomaccessiterator, Randomaccessiterator middle,randomaccessiterator last);Template<classRandomaccessiterator,classStrictweakordering>voidPartial_sort (Randomaccessiterator first,randomaccessiterator middle,randomaccessiterator last, StrictWeakOrdering comp);Template<classInputiterator,classRandomaccessiterator>randomaccessiterator partial_sort_copy (Inputiterator, Inputiterator last, Randomaccessiterator result_first,randomaccessiterator result_last);Template<classInputiterator,classRandomaccessiterator,classStrictweakordering>randomaccessiterator partial_sort_copy (Inputiterator, Inputiterator last, Randomaccessiterator result_first,randomaccessiterator result_last, Compare comp);

After understanding the sort and stable_sort, it is easier to understand the partial_sort. First look at its use: There are 10 students in the class, I want to know who is the lowest score of 5. If you don't have partial_sort, you need to sort all the people in order, and then take the top 5. Now all you have to do is sort the minimum score of 5, and modify the above procedure as follows:

Stable_sort (Vect.begin (), Vect.end (),less<student> ()), replaced by: Partial_sort (Vect.begin (), Vect.begin () +5, Vect.end (),less<student> ());

The output results are:

------before sort ... Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52winter:77andyer:63lily: 76Maryia: | -----after sort .... Bush: 52Jimy: 56Jone: 56andyer:63tom: 74Mary: 92Jessy: 85winter:77lily: 76maryia:89

Do you know the benefits? When the amount of data is small, may not see the advantage, if it is 1 million students, I want to find the lowest score of 5 people ...

Partial_sort uses the heap ordering (Heapsort), which in any case is N*log (n). If you want to use Partial_sort to achieve a full order, you just have to make middle=last.

Partial_sort_copy is actually a combination of copy and Partial_sort. The number of sorted (copied) is the smaller of [the Result_first, the result_last]. If the [Result_first, result_last) interval is greater than the [before] interval, then Partial_sort is equivalent to the combination of copy and sort.

1.6 Nth_element Specify the ordering of elements

Nth_element an easy to read but explain the more troublesome sort. It would be more convenient to use the example:

There are 10 students in the class, and I'd like to know the students who scored in the bottom 4th place.

If you want to meet the above requirements, you can use sort order, and then take the 4th position (because it is from small to large row), smarter friends will use Partial_sort, only the top 4, and then get the 4th place. In fact this is you or waste, because the top two you do not need to sort at all, at this time, you need to nth_element:

Template <class randomaccessiterator>void nth_element (Randomaccessiterator, Randomaccessiterator Nth,randomaccessiterator last); Template <classclass strictweakordering>void nth_element ( Randomaccessiterator, Randomaccessiterator Nth,randomaccessiterator last, strictweakordering comp);

For the above instance requirements, you only need to modify the program in 1.4 according to the following requirements:

Stable_sort (Vect.begin (), Vect.end (),less<student> ()), replaced by: Nth_element (Vect.begin (), Vect.begin () +3, Vect.end (),less<student> ());

The results of the operation are:

------before sort ... Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52winter:77andyer:63lily: 76Maryia: | -----after sort .... Jone: 56Bush: 52Jimy: 56andyer:63jessy: 85Mary: 92winter:77tom: 74Lily: 76maryia:89

Who's the fourth one? Andyer, this bad guy. Why is begin () +3 instead of +4? I didn't even care when I started writing this article, and then

__ILOVEVC__The reminder, found the problem. Begin () is the first, begin () +1 is the second, ... begin () +3 of course is the fourth.

1.7 Partition and Stable_partition

As if these two functions were not used for sorting, the ' classification ' algorithm would be more appropriate. Partition is to divide the elements of an interval into two classes according to a certain condition. Its function prototype is:

Template <classclass Predicate>forwarditerator partition (ForwardIterator, ForwardIterator last, predicate pred)Template <classclass predicate> ForwardIterator stable_partition (ForwardIterator, ForwardIterator last, predicate pred);

Take a look at the application: 10 students in the class, counting all students who have not passed (below 60 points). You just need to replace the program in 1.4 with the following format:

Stable_sort (Vect.begin (), Vect.end (),less<student> ()), replaced by: Student Exam ("Pass"); Stable_ Partition (Vect.begin (), Vect.end (), bind2nd (less<student> (), exam));

The output is:

------before sort ... Tom: 74Jimy: 56Mary: 92Jessy: 85Jone: 56Bush: 52winter:77andyer:63lily: 76Maryia: | -----after sort .... Jimy: 56Jone: 56Bush: 52Tom: 74Mary: 92Jessy: 85winter:77andyer:63lily: 76maryia:89

See, Jimy,jone, Bush (no wonder that the President of the United States is stupid) failed. And the use of stable_partition, the relative order between elements is unchanged.

2 Sort and container

The main vectors of the standard containers in STL, List, deque, String, set, Multiset, map, Multimay, where set, Multiset, map, Multimap all store their elements in a tree-structured way. See:

__Learning STL Map, the data structure base of STL set__. So in these containers, the elements are always ordered.

The iterator types of these containers are not random iterators, so the sort functions mentioned above are not available for these containers. The sort function above is available for the following containers:

If your own defined container also supports random iterators, there is no problem using the sort algorithm.

For the list container, list comes with a sort member function List::sort (). It is similar to the sort in the algorithm function, but the list::sort is sorted based on the pointer, that is, all data movement and comparisons are implemented by the pointer, so the sorted iterator remains in effect (the iterator of the sort in vector is invalidated).

3 Select the appropriate sort function

Why choose the right sort function? You may not care about efficiency (where the efficiency refers to the running time of the program), or the amount of data you have is small, so you think it doesn't matter which function you use.

In fact, even if you don't care about efficiency, if you choose the right sort of function, you will make your code easier to understand, you will make your code more scalable, and gradually develop a good habit, it is important.

If you've ever used qsort in C, and you want to know qsort and their comparisons, I'll tell you, qsort and sort are the same, because they're all sort of fast. In terms of efficiency, the following sort algorithms are sorted, with efficiencies ranging from high to low (time-consuming from small to large):

- Partion
- Stable_partition
- Nth_element
- Partial_sort
- Sort
- Stable_sort

Remember, previously translated effective STL article, which on

__How to select a sort function__The summary is very good:

- For vector, string, deque, or array containers, you can choose sort or stable_sort;
- If you only need to get top n elements in a vector, string, deque, or array container, the partial sort partial_sort is preferred.
- For vectors, string, deque, or array containers, you need to find the nth position element or you need to get top N and the inner order of the N, which does not matter, nth_element is ideal;
- If you need to separate elements that satisfy a condition or not satisfy a condition from a standard sequence container or array, you'd better use partition or stable_partition;
- If you use the list container, you can use the partition and Stable_partition algorithms directly, and you can use List::sort instead of sort and stable_sort sorting. If you need to get a partial_sort or nth_element sort effect, you must use it indirectly. As described above, there are several ways to choose.

In short, remember a word:

**if you want to save time, do not detours, do not go the extra road!**
4 Summary

Discussion technology is like a bottomless pit, which can often be easily extended by a few other technical points. So we need to look at the problem from a global perspective, just like looking at the sort algorithm in the STL. In fact, there are make_heap, sort_heap and other sorting algorithms in STL. Not mentioned in this article. In this paper, an example is given to explain the characteristics of the sorting algorithm in STL, and how to choose the appropriate algorithm in the actual situation is summarized.

5 reference documentation

__clause 31: How to select a sort function__
__The ____Standard librarian:sorting in the Standard Library__
__effective STL Chinese version__
__Standard Template Library Programmer ' s Guide__