I've almost understood many STL algorithms until I've reached the algorithm std::nth_element
. I 'm stuck on it; I don't know how it works and it does do exactly.
For education and understanding sake can someone explain to me how the algorithm std::nth_element
works?
std::vector<int> v{ 9, 3, 6, 2, 1, 7, 8, 5, 4, 0 };
std::nth_element(v.begin(), v.begin() 2, v.end());
for (auto i : v)
std::cout << i << " ";
std::cout << '\n';
The output:
1 0 2 3 6 7 8 5 4 9
- So where is
nth
element here? - How and what the algorithm does?
- Does it do some sort of partial sorting?
Here is some explanation from cppreference.com:
nth_element
is a partial sorting algorithm that rearranges elements in [first, last) such that:
- The element pointed at by nth is changed to whatever element would occur in that position if [first, last) was sorted.
- All of the elements before this new nth element are less than or equal to the elements after the new nth element. More formally, nth_element partially sorts the range [first, last) in ascending order so that the condition
!(*j < *i)
(for the first version, orcomp(*j, *i) == false
for the second version) is met for any i in the range [first, nth) and for any j in the range [nth, last). The element placed in the nth position is exactly the element that would occur in this position if the range was fully sorted.nth may be the end iterator, in this case the function has no effect.
- I am still confused about it. What is nth element and how to implement a possible algorithm like that?. For education sake I've mimicked many STL algorithms. Thank you so much!
CodePudding user response:
So where is nth element here?
The n-th element is the 2
at index 2
because thats what you asked for when you passed begin() 2
.
The element pointed at by nth is changed to whatever element would occur in that position if [first, last) was sorted.
This means that, if the vector was sorted, the order of elements would be
0 1 2 3 4 5 6 7 8 9
^--- begin() 2
You asked to have 3rd largest element at index 2 (3rd position), and thats what the algorithm does.
In addition it puts all elements smaller in the front and all elements larger in the back:
!(*j < *i)
(for the first version, orcomp(*j, *i) == false
for the second version) is met for any i in the range [first, nth) and for any j in the range [nth, last).
Let's use indices rather than iterators, then for any i < 2
and any j > 2
it holds that v[i] < v[j]
. In other words, 1
and 0
are both smaller than any element in 2 3 6 7 8 5 4 9
.
CodePudding user response:
I will explain my code first before getting into your problem
for example I have code like this
int m_array_biasa[8] {3,2,10,45,33,56,23,47};
and I use it normally like
std::nth_element(m_array_biasa, m_array_biasa 4, m_array_biasa 8);
so nth element in here is 4[33], the rule of std::nth_element is that the number on the left of nth must be less than or equal to and the number on the right must be greater than nth
and don't forget, data must be sorted from small to large (default)
so the data that was originally
3,2,10,45,33,56,23,47
changed to
2 3 10 23 33 45 47 56
my nth is 4[33], so the above rules apply (without including the sorting result)
and the result is
3 2 10 23 33 56 45 47
note above, position 33 has not changed, but sometimes it's a bit confusing, for example we change 33 to 1, then the result
2 1 3 10 23 45 47 56
what happened here, why did the number 1 move (replaced by 23), why didn't it stay like the previous number 33, I said before that we have to sort the data first (see sorting above), it turns out that index nth[4] is number 23 , then the number 1 is replaced with the number 23, why should it be replaced?, see the nth_element rule
now on to your question.
std::vector<int> v{ 9, 3, 6, 2, 1, 7, 8, 5, 4, 0 };
std::nth_element(v.begin(), v.begin() 2, v.end());
v.begin() contains 9, v.begin() 2 contains 6, remember, nth_element will sort it first
0 1 2 3 4 5 6 7 8 9
and your output is
1 0 2 3 6 7 8 5 4 9
the nth[2] above (acccording your v.begin() 2)p is 2, so 2 here is like a reference for other data, the data before 2 must be less than it, and after it must be more than it