2011-03-25 13 views
7

Así que estoy tratando de hacer un programa básico para aprender los conceptos básicos de C++, estoy generando 100 números aleatorios del 0 al 100 y almacenándolos en un vector, entonces estoy mostrando la suma, media, mediana, modo, alto y bajo del vector. Tengo todo lo demás hecho, excepto el modo que es donde me quedo atascado. Aquí está el código que tengo hasta ahora.Encontrar el modo del vector de Ints en C++

int modeFunction() 
    { 
     numMode = 0; 
     count = 0; 
     for (int n = 0; n < 100; n++) 
     { 
      for (int y = 0; y < 100; y++) 
      { 
       if (numVector.at(y) == numVector.at(n)) 
       { 
        numMode = numVector.at(y); 
        count++; 
       } 
      } 

     } 
     return numMode; 
    } 

Después de eso me quedo atascado porque en mi opinión eso debería funcionar, pero no es así. Acaba de poner el último número, generalmente 100. Cualquier ayuda sería muy apreciada.

+1

si '' myVector' es un std :: vector '(parece que al menos), se puede indexar como si fuera una matriz:' myVector [y] 'y' myVector [n] 'se produce lo mismo que la versión 'myVector.at', pero se ve mejor. :) – Xeo

+2

@Xeo: la diferencia es que 'at' tiene un comportamiento definido cuando el índice está fuera de rango. Podría decirse que 'operator []' es una micro-optimización, aunque como dices también es una diferencia de estilo. –

+0

@Steve: Ah, gracias por ese bocado.:) No se molestó con 'at' todavía, pero una matriz normal también tiene un comportamiento indefinido para el acceso fuera de rango, aunque ciertamente es bueno haber definido comportable cuando lo necesita. :) – Xeo

Respuesta

7

ya que todos los valores se encuentran entre 0 y 100, usted puede encontrar el modo eficiente con un histograma: enfoque

std::vector<int> histogram(101,0); 
for(int i=0; i<100; ++i) 
    ++histogram[ numVector[i] ]; 
return std::max_element(histogram.begin(), histogram.end()) - histogram.begin(); 
5

Como el modo es el número que ocurre con mayor frecuencia, no debe cambiar numMode a menos que el número de nuevos cuente sea mayor que numMode.

EDITAR: Para aclarar, debe mantener un conteo separado para el elemento actual y el número actual que usted piensa que es el modo. Idealmente, establecer newMode en el primer elemento es un buen enfoque.

Además, el modo no es necesario por sí solo (es decir, "1 1 2 2"). Es posible que desee tener eso en cuenta si le importa eso.

newMode = element[0] 
modeCount = # of occurrence of newMode 

for (i-th element from [1 to end]) { 
    tmpCount = # of occurrence of element[i] 
    if tmpCount > modeCount { 
    newMode = element[i] 
    modeCount = tmpCount 
    } 
} 
0

Su algoritmo es incorrecto: genera el último número en la matriz porque eso es todo lo que puede hacer. Cada vez que el número en el índice y coincide con el número en el índice n, sobrescribe los resultados del n anterior. Dado que está utilizando las mismas condiciones del bucle, y yn son siempre la misma en al menos un punto en el bucle anidado para cada posible valor n - y siempre se va a terminar con numMode siendo numVector.at(99).

necesita cambiar su algoritmo para memorizar el recuento para cada índice n lo largo del camino (o al menos lo que n índice terminó con la mayor count), para que pueda saber al final del bucle n qué entrada ocurrió la mayoría de las veces.

1

Soluciones alternativas. Nota: no probado.

int mode1(const std::vector<int>& values) 
{ 
    int old_mode = 0; 
    int old_count = 0; 
    for(size_t n=0; n < values.size(); ++n) 
    { 
     int mode = values[n]; 
     int count = std::count(values.begin()+n+1, values.end(), mode); 

     if(count > old_count) 
     { 
      old_mode = mode; 
      old_count = count; 
     } 
    } 
    return old_mode; 
} 

int mode2(const std::vector<int>& values) 
{ 
    return std::max_element(values.begin(), values.end(), [](int value) 
    { 
     return std::count(values.begin(), values.end(), value); 
    }); 
} 
0

Modo significa un número con la frecuencia más alta. La lógica debería ser -

//Start of function 

int mode = 0, globalCount = 0 ; 
// Start of outer for loop 
for i = 0 to length - 1  
    int localCount = 0 

    // Start of inner for loop 
    for j = 0 to length - 1  
    if vec[i] == vec[j]  
    ++localCount  
// End of Inner for loop 

if (localCount > globalCount) 
    globalCount = localCount 
    mode = vec[i] 
// End of outer for loop 

if globalCount > 1 // This should be checked whether vec has repetitions at all 
    return mode 
else 
    return 0 

// End of function 
+0

@Cistoran: la lógica puede mejorar aún más la eficiencia, pero esto es lo que el algoritmo debe estar de acuerdo con su proceso de pensamiento. – Mahesh

0

de bmcnett funciona muy bien si el número de elementos son lo suficientemente pequeños . Si tiene una gran cantidad de elementos pero el valor de todos los elementos está dentro de un rango pequeño, el mapa/hashmap funciona bien. Algo así como

typedef std::pair<int, int> mode_pair; 

struct mode_predicate 
{ 
    bool operator()(mode_pair const& lhs, mode_pair const& rhs) 
    { 
    return lhs.second < rhs.second; 
    } 
}; 

int modeFunction() 
{ 
    std::map<int, int> mode_map; 
    for (int n = 0; n < 100; n++) 
    mode_map[numVector[n]]++; 
    mode_predicate mp; 
    return std::max_element(mode_map.begin(), mode_map.end(), mp)->first; 
}