2012-03-21 11 views
19

Lo que estoy tratando de hacer:¿La mejor manera de dividir un vector en dos matrices más pequeñas?

Estoy tratando de dividir un vector en dos matrices independientes. El vector int actual contiene un elemento por línea en un archivo de texto. El archivo de texto es una lista de enteros aleatorios.

Cómo tengo la intención de hacerlo:

Mi idea actual es crear dos matrices int regulares, a continuación, iterar sobre todo el vector y copiar n/2 elementos a cada una de las matrices.

Lo que me gustaría saber:

¿Cuál es la forma más elegante de llevar a cabo mi tarea? Tengo la sensación de que puedo hacer esto sin iterar sobre el vector varias veces.

Código:

#include <vector> 
#include <fstream> 
#include <iterator> 
#include <iostream> 
using namespace std; 

vector<int> ifstream_lines(ifstream& fs) 
{ 
    vector<int> out; 
    int temp; 
    while(fs >> temp) 
    { 
    out.push_back(temp); 
    } 
    return out; 
} 

vector<int> MergeSort(vector<int>& lines) 
{ 
    int split = lines.size()/2; 
    int arrayA[split]; 
    int arrayB[split]; 
} 

int main(void) 
{ 
    ifstream fs("textfile.txt"); 
    vector<int> lines; 
    lines = ifstream_lines(fs); 

    return 0; 
} 

Gracias :)

+0

lo recomiendo algo de la '' cabecera (http://en.cppreference.com/w/cpp/algorithm). 'std :: copy' o' std :: move' pueden ser de su interés. –

+0

Me gusta cómo se formula la pregunta. No suele ver buenas preguntas estructuradas como esta de usuarios nuevos. – MOnsDaR

+0

si no planea cambiar el tamaño de las 2 matrices, puede echar un vistazo a 'array_view' – sp2danny

Respuesta

44

Use iteradores.

std::vector<int> lines; 
// fill 
std::size_t const half_size = lines.size()/2; 
std::vector<int> split_lo(lines.begin(), lines.begin() + half_size); 
std::vector<int> split_hi(lines.begin() + half_size, lines.end()); 

Desde rangos de iterador representan la mitad de las gamas abiertas [begin, end), no es necesario añadir 1 a la segunda comenzará iterador: lines.begin() + half_size no se copia en el primer vector.


Tenga en cuenta que cosas como

int split = lines.size()/2; 
int arrayA[split]; 
int arrayB[split]; 

no son estándar C++ (y como tal no portátil). Estas son las llamadas matrices de longitud variable (VLA para abreviar) y son una cosa C99. Algunos compiladores los tienen como una extensión al compilar el código C++ (GCC, Clang). Siempre compile con -pedantic para recibir una advertencia. Estos VLA actúan de manera funky para los tipos que no son POD y generalmente no son útiles, ya que ni siquiera puede devolverlos.

+0

Muy buena respuesta, +1 para" no necesita agregar 1 al segundo iterador de inicio " –

2

Si sólo necesita una referencia a los números sin manipularlas, entonces usted puede hacer:

int *array_1 = &lines[0]; 
int *array_2 = &lines[lines.size()/2]; 

array_1 y array_2 son, en realidad, punteros al inicio y mediados del vector. Esto funciona porque STL garantiza que los vectores almacenan sus elementos dentro de una memoria continua. Tenga en cuenta que al hacer referencia a lines.begin() no se puede usar para esto.

1

Si no puede usar el código de Xeo respuesta debido a las reglas estrictas del compilador o si desea manera más genérica, tratar std::advance:

#include <vector> 
#include <iterator> 

size_t middle = input.size()/2; 
std::vector<int>::const_iterator middleIter(input.cbegin()); 
std::advance(middleIter, middle); 

std::vector<int> leftHalf(input.begin(), middleIter); 
std::vector<int> rightHalf(middleIter, input.end()); 
Cuestiones relacionadas