Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do I remove the smallest and largest element in an array in a manner that's appropriate to C++?

Tags:

c++

Let's say I have an array of ints and I want to call a function to remove the smallest and largest values. By remove I mean that if my initial array was 7 elements in length, the new array has 5 elements. The order of the remaining elements does not matter. I've come up with some ways to do it, but I'm not sure which one is the C++ "way" of doing it, if that makes sense.

What I have now is that I use std::sort to sort my array and then I use a for loop to copy the results starting from the second element and stopping at the second-to last element into a new array with the appropriate size. How should I return the array though?

I can't return the newly created array because it's a local variable to the function. I could pass the new array as an argument to the function, but isn't that more of an older, C-style way of doing this? I could also use std::vector, but then I'd have to wrap the array in a vector and then unwrap it (the numbers need to remain in an array of ints). Seems like overkill, doesn't it?

I'm coming from a Python background and I just want to know what's the more appropriate way to do this in C++.

like image 340
bao Avatar asked Aug 10 '10 19:08

bao


1 Answers

If the numbers had to remain in an array of ints and the order didn't matter, I would do it this way:

void MoveHiLoToEnd(int orig[], int size)
{
    int* last = orig + size - 1;
    int* maxp = std::max_element(orig, orig + size);
    std::iter_swap(maxp, last);
    int* minp = std::min_element(orig, orig + size - 1);
    std::iter_swap(minp, last - 1);

    //now the original array contains max and min elements moved.
    //to the end. You can ignore them or copy elements except
    //those last two to a new array, if really necessary.
}

The signature

int* MoveHiLoToEnd(int* begin, int* end);

is more in C++ library style and it could be changed to a template

template<typename ForwardIter>
ForwardIter RemoveHiLo(ForwardIter begin, ForwardIter end);

returning the iterator to the old min element (past the new truncated collection), but I doubt it's worth it. That would require different (less convenient I think) parameters in the call.

EDIT

Sorry template idea is bad. Things get complicated. You would have to require bidirectional iterator (which makes the template less universal than it could be with forward ones. for min and max_element forward is enough)

template<typename BidirectionalIterator>
BidirectionalIterator RemoveHiLo(BidirectionalIterator begin, BidirectionalIterator end);

or nonstandard input parameters, because you need iterator to the last element.

like image 187
Maciej Hehl Avatar answered Oct 26 '22 18:10

Maciej Hehl