-1

Since I am new in competitive programming so I am finding this a bit difficult. I encountered a code and I am not able to figure it out, need some help to understand it.

#include<iostream>
#include<algorithm>

using namespace std;
bool mycompare(int a ,int b){

    return a>b;
}

int main(){

    int a[]={5,4,3,1,2,6,7};
    int n =sizeof(a)/sizeof(int);

    sort(a,a+n,mycompare);

    for(int i=0; i<n;i++){
    cout<<a[i]<<"";
    }
    return 0;
}
output:
7 6 5 4 3 2 1 

How does this code work more specifically what does the mycompare function do in the code?

My doubt is that why haven't we passed any arguments in the mycompare() function inside the main() function since the prototype of the function is

bool mycompare(int a, int b);
JohanC
  • 71,591
  • 8
  • 33
  • 66
priyanshu
  • 21
  • 1
  • 5
  • 3
    What *do* you understand about it, and what have you done to try and understand the rest? – Scott Hunter Dec 06 '19 at 15:03
  • 2
    If you want to learn how [`std::sort`](https://en.cppreference.com/w/cpp/algorithm/sort) work, you need to learn more about sorting and sorting algorithms in general. Then it should become very clear why a *comparison* function is needed and how it's used. – Some programmer dude Dec 06 '19 at 15:04
  • `mycompare` compares two integers using `greater than`. If `a` is greater than `b`, the function returns `true`. `std::sort` takes in a comparator to be used, which is the `mycompare` function in this case. So it sorts using that comparison. – ChrisMM Dec 06 '19 at 15:08
  • mycompare function will be called internally by sort function. you are just passing the address of function which need to used. else default function will be called. – Nagappa Jun 04 '20 at 07:50

2 Answers2

0

A comparison-based sorting algorithm sorts the elements solely by pair-wise comparison, i.e., if a < b holds, then a has to be placed before b.

This is a fine approach, but if you limit yourself to using <, it only allows you to sort elements in an ascending order. What if you want to have them in descending order, or any other ordering? This is where the concept of a Comparator (or a Compare callable in the context of the C++ standard) comes into play: It is a binary predicate bool compare(element a, element b) that is supposed to replace the < operator, i.e., a < b becomes compare(a, b) instead. This generalization allows you to encapsulate all types of orderings, in your question you already provided an example where the comparison uses a greater-than operator >, which gives you the aforementioned descending sorted order.

As for how this works internally in C++, the details can be rather complicated, but you can look at it as this:

mycompare without any parameters is a function pointer, i.e. a pointer to the memory address where the machine code for mycompare starts. You can do something like

auto func_pointer = mycompare;
func_pointer(1, 2); // calls mycompare(1, 2)

By giving this function pointer as a parameter to std::sort, you replace the default < comparison function by your own. The way C++ works internally gives the additional advantage that this function call can most likely be inlined, i.e., the compiler avoids the function call can be avoided by copying the code from mycompare into the std::sort invocation, which can speed up your code significantly.

Tobias Ribizel
  • 5,331
  • 1
  • 18
  • 33
-2

std::sort takes a RandomIt (random iterator) as the first and second arguments that must satisfy the requirements of ValueSwappable and LegacyRandomAccessIterator. Instead of using a Plain-Old-Array of int, you want to use std::array which can then provide the iterators with the member functions .begin() and .end().

Using a proper container from the C++ standard template library makes sorting with std::sort trivial. You need not even provide a custom compare function to sort in descending order as std::less<int>() is provided for you (though your purpose may be to provide the compare function)

Your prototype for mycompare will work fine as is, but preferably the parameters are const type rather than just type, e.g.

bool mycompare(const int a, const int b)
{
    return a > b;
}

The implementation using the array container is quite trivial. Simply declare/initialize your array a and then call std::sort (a.begin(), a.end(), mycompare); A complete working example would be:

#include <iostream>
#include <algorithm>
#include <array>

bool mycompare(const int a, const int b)
{
    return a > b;
}

int main (void) {

    std::array<int, 7> a = { 5, 4, 3, 1, 2, 6, 7 };

    std::sort (a.begin(), a.end(), mycompare);

    for (auto& i : a)
        std::cout << " " << i;
    std::cout << '\n';
}

Example Use/Output

$ ./bin/array_sort
 7 6 5 4 3 2 1

Sorting the Plain Old Array*

If you must use a Plain-Old-Array, then you can use plain-old-pointers as your random iterrators. While not a modern C++ approach, you can handle the plain-old-array with std::sort. You can make use of the builtin std::greater<type>() for a descending sort or std::less<type>() for an ascending sort.

An implementation using pointers would simply be:

#include <iostream>
#include <algorithm>

int main (void) {

    int a[] = { 5, 4, 3, 1, 2, 6, 7 };
    size_t n = sizeof a / sizeof *a;

#if defined (ASCEND)
    std::sort (a, a + n, std::less<int>());
#else
    std::sort (a, a + n, std::greater<int>());
#endif

    for (size_t i = 0; i < n; i++)
        std::cout << " " << a[i];
    std::cout << '\n';
}

(same output unless -DASCEND is added as a define on the commandline, and then an ascending sort will result from the use of std::less<int>())

Look things over and let me know if you have further questions.

David C. Rankin
  • 81,885
  • 6
  • 58
  • 85
  • I would like to point out that all pointers to Swappable types fulfill the type requirements of `std::sort`, as pointers are the model example of a `RandomAccessIterator`. So while it is maybe not "modern C++" style to use them, there is nothing inherently wrong with it either. Especially the reference to `qsort` seems harmful to me. – Tobias Ribizel Dec 08 '19 at 08:59
  • I would not recommend any algorithms from the C standard library as long as there are alternatives in the C++ standard library. Also, due to the additional indirection introduced by the comparator function pointer, `qsort` is most likely much slower than the corresponding `std::sort`, which is especially important in competitive programming. Your second sentence seems to imply that you need additional boilerplate code to use `std::sort` with raw pointers. That is not the case, as I tried to clarify in my first comment. – Tobias Ribizel Dec 08 '19 at 09:25
  • I've updated with a Pointer example for code pre-STL. – David C. Rankin Dec 08 '19 at 09:28
  • I would be really surprised if gcc was using the exact same sorting code as the basis for `qsort` and `std::sort` when it comes down to it. The gcc `qsort` is a highly optimizes blend of *quicksort* utilizing an *insertion sort* when the number of partitions falls below 16 at my last check. It's always somewhat a "rabbit-trail" to snake through the git tree hopping from file to file to chase down the included pieces and macros. But I do agree with you, if C++ provides it, it's better to use it compared to where there is no C++ implementation, like `strtok`, etc.. – David C. Rankin Dec 08 '19 at 09:53
  • My claim was actually a bit stronger: Even if they both implemented the fastest state-of-the-art sorting algorithms, `qsort` could never come close to `std::sort`, since it cannot inline the comparator function pointer. There are [many](https://travisdowns.github.io/blog/2019/05/22/sorting.html) [benchmarks](https://martin-ueding.de/articles/qsort-vs-std-sort/index.html) [to that effect](https://stackoverflow.com/questions/4708105/performance-of-qsort-vs-stdsort). – Tobias Ribizel Dec 08 '19 at 10:04
  • Those are good links. The [qsort vs. std::sort](https://martin-ueding.de/articles/qsort-vs-std-sort/index.html) doesn't show a great disparity among `qsort` and `std::sort` for the gcc/g++ implementation or even between that and the clang/clang++ results as well. I guess the numbers could diverge more as the number of elements exceeds the 10E7 range shown on the graph, but what's there is in line with what I would expect. – David C. Rankin Dec 08 '19 at 10:12
  • I don't think it makes sense to continue this discussion further. Just note that the blog post you mentioned uses logarithmic scales for runtimes and speedups, and mentions a speedup of roughly 2 between `std::sort` and `qsort` for large inputs. This is also reflected in the other benchmarks I listed. – Tobias Ribizel Dec 08 '19 at 10:22