BUG: nlargest/nsmallest gave wrong result (#22752)
- [X] closes #22752 
- [X] tests added / passed
- [X] passes `git diff upstream/master -u -- "*.py" | flake8 --diff`
- [X] whatsnew entry

When asking for the n largest/smallest rows in a dataframe
nlargest/nsmallest sometimes failed to differentiate
the correct result.

I looked at the nsmallest/nlargest implementation for data frames and to
me it looks wrong. 

With ties in the first columns, the old algorithm picked all duplicates rather
than all values that lies on the border for the next tie-break iteration.
That meant that to find the top 5 values in a data frame like e.g:
   
[0 5] [0 4] [1 0] [2 3] [2 2] [2 1]

1. the algorithm would first pick the top 5 via the first column:
(That would be [1 0] [2 1] [2 2] [2 3] [0 4] [0 5])
2. It would then try to pick the values that were certain (that is the unique 
first column values, that is):
[1 0]
3. and go on for the next iteration with all rows where the first column value was non-unique but among the top 5:
That is: [2 3] [2 2] [2 1] [0 4] [0 5]
4. It would the compare the remaining on the second column, picking: [0 5] [0 4] [2 3] [2 2]
5. Finally returning: [1 0] [0 5] [0 4] [2 3] [2 2]

Which is not the correct result: [1 0][0 4] [2 3] [2 2] [2 1]

I've changed the algorithm so instead of tie-breaking on all values having duplicates in an earlier column, it will now tie break only on the duplicates of the largest/smallest value in a given column, so it will do:

1. Pick top 5 of column 1:
[1 0] [2 1] [2 2] [2 3] [0 4] [0 5]
2. zero is the border value, the rest is safe:
[1 0] [2 1] [2 2] [2 3]
3.  [0 4] [0 5] goes on to the next iteration:
4. 5 > 4 so [0 5] is the top 1 of what's left:
5. The result is:  [1 0] [2 1] [2 2] [2 3] [0 5]

Which is the correct result.