Article Review ~ In depth Tutorial On sort()

All criticism is welcome especially if you see any mistakes on the code. Be warned I am probably not the best writer in the world and this is my first tutorial I have ever done so ;p.

This tutorial is aimed at beginners that have some knowledge of C++ but have yet to dabble much with the STL. This is part of the a series of tutorials I am putting together about algorithms and the usefulness of the STL.

Also I have yet to actually go through this more then once to do spelling corrections and all that so this is basically a first draft.

Let me know what you think thank you :)

Beginning with STL Algorithms
Tutorial #1 the sort() Function

By Zereo

Sort Function

First before we start lets take a quick look at how the function looks and what it does.

Here is what the function looks like in its default form, and with the optional third parameter. Don’t worry I will explain each parameter and more in a second, but first take a look at each of these functions and see if you can figure out what each parameter does.

Example 1~ std::sort(myvector.begin(), myvector.end())

Example 2~ std::sort(myvector.begin(), myvector.end(), myCompFuncion)

So lets go dig into these and figure out what each does and why it does it. First lets go over what everything is.

Found in ~ #include <algorithm>

Parameter 1 myvector.begin()~ The first parameter is where you will be putting a iterator(Pointer) to the first element in the range that you want to sort. The sort will include the element that the iterator points to.

Parameter 2 myvector.end() ~ The second parameter is almost like the first but instead of putting a iterator to the first element to sort you will be putting a iterator to the last element. One very important difference is that the search won’t include the element that this iterator points to. It is [First,Last) meaning it includes the first parameter in the sort but it doesn’t include the second parameter in the sort.

Parameter 3 myCompFunction() Optional ~ I will only give a brief description here, because I will explain this parameter in more detail later. The third parameter is used to define how you do the search. For example if you have a struct that has 3 different variables in it how does the function know which one to sort? Or how does it know how it should sort it? This is what this parameter is for. I will explain this more in a bit.

When we use the sort function to sort a array our arguments will look a bit different then when we use it on a vector for example. In the example above when we pass in intArray as a argument we are telling the function to start the sort at the beginning of the array. If we wanted it to start the sort at the second element of the array we would do sort(intArray + 2, intArray + SIZE);. So when we do intArray + SIZE for the second argument we are telling the array to sort up to the last element in the array.

Sorting Vectors and other STL Containers Example

Warning: This example uses features that are only available in C++11 compilers. If you try this code and it doesn’t compile you most likely don’t have a C++11 compiler. Since the last time I checked Code::Blocks IDE comes with a C++11 compiler and you can enable it by going to settings->compiler->compiler settings->compiler flags-> and then you should see a checkbox that says something like Have g++ follow the C++11 ISO C++ language standard. Enable that and click ok and you should be good to go.

First as you can see the sorting function works almost the same as on a array but we just have to pass our arguments a little differently. Since the first parameter in sort() accepts a iterator(pointer) to the first element we want to sort we can pass stringVec.begin() to it and it will start sorting at the first element in the vector. The same goes for stringVec.end() for the second parameter because remember stringVec.end() is a pointer to 1 past the last element in the container, and the sort function sorts up to but not including what we pass in as the second parameter.

You also probably noticed that the sort works on things other then numbers. When we printed out the vector of strings it gave us a nice and neat vector that holds the names in their alphabetical order.

The Third Optional Parameter.

The third parameter in the sort() function is actually a very useful feature. It allows up to define how the sort() function will actually perform the search. This parameter is optional because for basic types and containers it isn’t needed most of the time. But what if we wanted to change how the container was sorted by having it sort by descending instead of ascending? Or what if we had a container full of a special type of class we created and need to sort that container a special way? Well this is where the third parameter comes in.

Making it sort by descending order example.Warning: Uses C++11 Code

1234567891011121314151617181920212223242526

// Vector Sorting Descending Example.// By Zereo 04/22/13#include <iostream>#include <algorithm>#include <vector>usingnamespace std;
// We need this function to define how to sort// the vector. We will pass this function into the// third parameter and it will tell it to sort descendingly.bool wayToSort(int i, int j) { return (i>j); }
int main()
{
vector<int> intVec = {56, 32, -43, 23, 12, 93, 132, -154};
// Do not include the () when you call wayToSort// It must be passed as a function pointer or function object
sort(intVec.begin(), intVec.end(), wayToSort);
for (int i : intVec)
cout << i << " ";
return 0;
}

The Function

First lets look at the function. What we did is we created a function that will determine whether i > j if it is it will return true, if not it will return false every time it is called. The sort function will automatically assign a element to both i and j.

The function you make needs to have a return type of bool and must return only types that can be converted into bool.

So when we defined bool wayToSort(int i, int j) { return (i>j); } We are saying we wanted it to sort descending because i > j whereas ascending would be i < j.

For a lot of programs we aren’t storing just ints, strings, or doubles. Instead we are making complicated classes with that have multiple number and string members and storing them in a container. So when we want to sort that container of our class objects we need to define a special function that will tell the sort() function how it should sort them object.

So for my last example lets say we have a struct that represents a person and it looks like this.

123456

struct Person
{
string name;
int age;
string favoriteColor;
};

As you can see it has three members: name, age and color. Now lets say we have a program that has a vector full per Person objects, and we need a way to be able to sort them by their name, age or favorite color at certain points in the program.

One way would be to make a function for each different way of sorting. The example below is a program that will ask the user to enter 5 people’s names, ages, and favorite colors. It will then prompt a menu with different sorting options. Each of them sorting options sorts the container a certain way (By name, age or color).

This function is actually very similar to the one we just made before except for we changed two things. We changed the parameter types from int to type Person, and we also changed the return calculation a bit.

First let’s go over the change to the parameters.

The reason why we had to change the parameters from int to type Person, is because the container we are sorting is of type vector<Person>. And in order to be able to call the equation lhs.name < rhs.name the parameters would have to be of type Person.

Secondly we changed the return equation to (lhs.name < rhs.name). Can you guess what this equation is asking? Remember that both lhs and rhs are pointing to a separate element in the container (Like lhs is element 1 and rhs is element 2). So when we say lhs.name we are telling it to access element 1’s object and then access that objects name member. The same goes for rhs.name but is it accessing element 2’s object instead. So when we say to return lhs.name < rhs.name we are asking it is rhs’s object’s name less then rhs’s objects name.

Well that is all for this tutorial, I hope this helped anyone reading it. If you have any comments (Especially on any mistakes) on the article/tutorial please let me know I enjoy any type of feedback good or bad.

The same goes for any questions, if you don’t understand anything or the way I explained something didn’t make sense (Very likely ;p) please let me know through a reply here or through a PM. I would be glad to help answer any questions you have.

If this tutorial doesn’t totally bomb I might write a series of tutorial/articles aimed at beginners on the many uses of the STL algorithms.

Style suggestions:1) I like to order headers alphabetically when including them2) I like to omit the return statement in main() ... it's not something meaningful to write return 0; over and over3) I think you shouldn't be usingnamespace std;

Your "Sorting User Made Types" example is too long. Keep focused on what you want to show, don't build a menu. Source code examples in articles should be "optimized" for reading, and not for compiling, in my opinion.

And where are the lambdas?! :)

Finally, I wouldn't write a series of articles, if I were you. I would rather write a single, large article with a Contents area with links to the sections. I'm pretty sure it's allowed to add links in the header names but I didn't test, then you could have "jump buttons", like [next], [prev] and [index].

@Cubbi Thank you for the suggestions, will be rewriting part of the tutorial to include std::begin and std::end along with a minor note about them. Will also be working on talking about operator<.

@Catfish Thank you for the suggestions. I like your style suggestions, especially the using namespace std; one. I figured I would make it as beginner friendly as possible, but now that you point it out you are right I shouldn't be promoting using it. Also thank you for the links on that will be sure to include them in the article.

Your "Sorting User Made Types" example is too long. Keep focused on what you want to show, don't build a menu. Source code examples in articles should be "optimized" for reading, and not for compiling, in my opinion.

Ya that was the one big part that I was debating on with myself. On one side since the tutorial is aimed mainly at beginners I wanted to have one semi complete program that that they could copy and paste and play with. But on the other side it is taking up a huge amount of real estate and might be unnecessary. I think what I might do is optimize it down to just showing how to sort complicated types and then include a attachment that they can download if they want a full program example.

And where are the lambdas?! :)

They will be coming ;p this is only the first draft of the article and have much to add to it.

Finally, I wouldn't write a series of articles, if I were you. I would rather write a single, large article with a Contents area with links to the sections.

Ohh nice I didn't think I could do that. That actually makes it much easier since as you said I can just make a large article and include a Contents area with links to each section. Thank you for the suggestion.

@MiiNiPa

And I think std::less, std::greater and others is worth mentioning, however I don't think those who uses this tutorial will find it useful yet.

That is actually a great idea. Maybe add in a quick mention about using them for the comparative parameter like sort(intVec.begin(), intVec.end(), std::greater<int>()); since that would be useful for beginners.

Thanks everyone for the suggestions again, will be working on doing updates and adding more the to article. After I feel everything is corrected and looks good will submit it here and then just do updates to the article itself and hopefully turn it into a whole article on using the STL algorithms.

Maybe you could add a brief paragraph explaining the type of algorithm that sort uses and its time complexity. For example, it uses is a blah blah optimized, blah blah quick sort algorithm with guaranteed time complexity of blah blah blah for blah of blah.

Alghorithm used by sort is implementation defined. Complexivity should not exceed O(N·log(N)) for sort() or O(N·log2(N)) for stable_sort() (If addititional memory is used, complexivity should not exceed O(N·log(N)) too)

@ Zereo: I think I said this before, but I really think you must begin with an introduction about iterators.

You must explain what iterators are used for, and how they relate to pointers (like your array example shows). If you do this, then I suggest giving a simple example of a function template you write yourself to demonstrate the iterator pattern in C++.

It shouldn't be too hard to explain how to declare a lambda to accept parameters, to capture variables and to return a value. Then using them becomes easy, just plug them into the algorithms. The small overhead is worth it... again in my opinion.

Lambda functions can be used in many cases. I think that it is better to create another small tutorial about lambdas and reference it from other articles: "Lambdas often used as comparator function (more about lambdas here)"

Default form as in the one used most often by beginners who this tutorial is for and optional parameter as in you don't need to include it. Personally I feel its not really necessary to get to go into the details of how the function is defined since the tutorial is geared at beginners. You don't need to know the details of how it is defined to know how to use it. But thank you for your input.

Let me know if anyone else sees a problem with the way that is worded and I will change it.