How to remove the smallest and largest element in an array according to 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 deletion, I mean that if my initial array consisted of 7 elements in length, the new array has 5 elements. The order of the remaining elements does not matter. I came up with some ways to do this, but I'm not sure which one is the "way" of C ++, if that makes sense.

Now I have the use of std :: sort to sort my array, and then I use the for loop to copy the results, starting from the second element, and stopping at the second-last element in the new array using the appropriate size. How do I return an array?

I cannot return the newly created array because it is a local variable for the function. I could pass a new array as an argument to a function, but isn't this an older C-style way? I could also use std :: vector, but then I would have to wrap the array in a vector and then expand it (the numbers should remain in the ints array). It seems like it's overkill, right?

I come from the Python background, and I just want to know which more suitable way to do this in C ++.

+5
source share
8 answers

If the numbers were to remain in the int array and the order doesn't matter, I would do it like this:

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.
}

Signature

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

more in the style of a C ++ library , and it can be changed to a template

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

min ( ), , . ( , ) .

, . . ( , , min max_element forward )

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

, .

+8

std::vector<int> .

using std::vector;

vector<int> WithoutHiLo(vector<int> orig)
{
     std::sort(orig.begin(), orig.end());
     vector<int> newVec = vector(orig.size());
     std:copy(&orig[1], &orig[orig.size()-1], &newVec[0]);
     return newVec;
}

UPDATE ( ):

vector<int> WithoutHiLo(vector<int> orig)
{
     std::sort(orig.begin(), orig.end());
     return vector(&orig[1], &orig[orig.size()-1]);
}

:

vector<int> WithoutHiLo(int orig[], int size)
{
     std::sort(&orig[0], &orig[size]);
     vector<int> newVec = vector(size);
     std:copy(&orig[1], &orig[size-1], &newVec[0]);
     return newVec;
}
+7

: min max, min max. , .

++ 03. , , - , min_element max_element. .

++ 0x minmax_element ( minmax). , ++ 0x, std::minmax_element, <algorithm>. , Boost Boost/ .

:

int array[] = {4, 7, 6, 5, 9, 4, 3, 1, 11};

// see footnote for begin and end
std::pair<int*, int*> mm = minmax_element(begin(array), end(array));

( ) . , ala:

// and take care your array has enough elements!
std::swap(*mm.first, end(array) - 2);
std::swap(*mm.second, end(array) - 1);

; O (1). , , , / ; O (N).

. - erase_minmax.

< > * begin end , :

template <typename T, size_t N>
T* begin(T (&pArray)[N])
{
    return pArray;
}

template <typename T, size_t N>
T* end(T (&pArray)[N])
{
    return pArray + N;
}

>

+4

STL.

std::vector<int> vec; 
//populate your vector
vec.erase (max_element(vec.begin(), vec.end()) );
vec.erase (min_element(vec.begin(), vec.end()) );

, , , , .

+1

. , int min max? .

#include <vector>
#include <stdio.h>

void
rm_minmax(int* x, int sz, std::vector<int>& v) {
    int min = x[0];
    int max = x[0];
    int Sz = sz;

    while (sz) {
        int dv = x[sz-1];
        if (dv < min) min = dv;
        if (dv > max) max = dv;
        sz--;
    }

    for (int i=0; i < Sz; i++) {
        if (x[i] != min && x[i] != max) v.push_back(x[i]);
    }
}

int
main(int argc, char** argv) {
    int foo[] = { 5, 1, 33, 22, 54, 1, 44, 54 };
    int sz = sizeof(foo)/sizeof(int);
    std::vector<int> x;
    rm_minmax(foo, sz, x);
    sz = x.size();
    for (int i=0; i < sz; i++) printf("%d\n", x[i]);

}

+1

, . , .

, ./a.out < /tmp/numbers, , echo 1 5 2 10 -2 0 | ./a.out

#include <algorithm>
#include <iostream>
#include <iterator>
#include <vector>

template<class T, class U>
U copy_without_min_max(T in_begin, T in_end, U out)
{
    typedef typename std::iterator_traits<T>::value_type value_type;
    // min and max hold the min and max values found so far in the loop.
    value_type min, max;
    // small and big hold the values from the current pair being evaluated.
    value_type small, big;

    typename std::iterator_traits<T>::difference_type len = std::distance(in_begin, in_end);
    // in_stop is either the end of input or one less if length is odd.
    // This is needed so that in_begin will equal in_stop while advancing 2 at a time.
    T in_stop(in_end);
    T in_next(in_begin);
    ++in_next;
    // evaluate the first pair to find initial min,max values.
    if ( *in_begin < *in_next ){
        min = *in_begin;
        max = *in_next;
    } else {
        min = *in_next;
        max = *in_begin;
    }
    if ( len % 2 != 0 ) { // if len is odd
        --in_stop;
    }
    std::advance(in_begin, 2);

    // Advance two elements at a time tracking min and max as we go.
    // Whenever a previous min or max is evicted, output it to the destination.
    // Whenever a min or max is confirmed, output the element to the destination.
    while( in_begin != in_stop ) {
        in_next = in_begin;
        ++in_next;
        if ( *in_begin < *in_next ) { // one comparison
            small = *in_begin;
            big = *in_next;
        } else {
            small = *in_next;
            big = *in_begin;
        }
        if ( min > small ) { // one comparison
            *out++ = min;
            min = small;
        } else {
            *out++ = small;
        }
        if ( max < big ) { // one comparison
            *out++ = max;
            max = big;
        } else {
            *out++ = big;
        }
        std::advance(in_begin, 2);
    }
    // Special case for odd number of elements.
    // Output either the last element or min or max, depending.
    if ( in_begin != in_end ) {
        if ( *in_begin > min && *in_begin < max ) {
            *out++ = *in_begin++;
        } else if ( *in_begin < min ) {
            *out++ = min;
        } else if( *in_begin > max ) {
            *out++ = max;
        }
    }
    return out;
}

int main()
{
    std::vector<int> in;
    std::copy(
        std::istream_iterator<int>(std::cin),
        std::istream_iterator<int>(),
        std::back_inserter(in)
    );
    copy_without_min_max(
        in.begin(),
        in.end(),
        std::ostream_iterator<int>(std::cout, " ")
    );
    std::cout << std::endl;

    return 0;
}
+1

STL- int , , , , .

: .

, , STL, .

//Other stuff here...
int test[] = {5, 4, 3, 2, 1};
JunkFunc(test);
//whatever else your program needs to do afterward...

void CFlirPumpDlg::JunkFunc(int *arr)
{
int junkArr[] = {1, 2, 3, 4, 5};
    //The above array is just dummy data; removing the high/low would go here
memcpy(arr, &junkArr, sizeof(junkArr));
}
0

++ - "" ++ ( ). ; vector; .

foo.delete_first(), foo - .

Here is my solution. It gives you a new array (allocated on the heap) with the characteristics you want. It will handle duplicate max / min values. My solution has more lines of code than the STL solution, and I would recommend using STL if possible.

//Returns a new'd array of type T.
//Delete when done.
// Big-O = O(std::sort(len)) + len + O(cost-of-new)
template<typename T>
T* filter(T* t, int len)
{
  T* trimmed;
  std::sort(t[0], t[len-1]); //consider that this will not compile if T is not comparable

  //Here you could use a predicate approach, but let write it out...
  int num_mins = 1; //t[0] is always min
  int num_maxes = 1; //t[len-1] is always max
  for(int i = 0; i < len; i++)
  { 
     if(t[i] == t[0])
       num_mins++;
     if(t[i] == t[len-1]) 
       num_maxes++;
  }

  trimmed = new T[len - (num_mins + num_maxes)];
  return trimmed
}
0
source

All Articles