2012-03-21 9 views
19

Co usiłuję zrobić:Najlepszy sposób na podzielenie wektora na dwie mniejsze tablice?

Próbuję podzielić wektor na dwa oddzielne tablice. Bieżący wektor int zawiera element na wiersz w pliku tekstowym. Plik tekstowy jest listą losowych liczb całkowitych.

Jak mam zamiar zrobić:

Mój obecny pomysłem jest utworzenie dwóch regularnych int tablice, a następnie iteracyjne nad całą wektor i skopiuj n/2 elementów do każdej z tablic.

Co chciałbym wiedzieć:

Jaki jest najbardziej elegancki sposób realizacji moje zadanie? Mam wrażenie, że mogę to zrobić bez wielokrotnego powtarzania wektora.

Kod:

#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; 
} 

Dziękuję :)

+0

polecam coś z '' nagłówku (http://en.cppreference.com/w/cpp/algorithm). 'std :: copy' lub' std :: move' mogą być interesujące. –

+0

Lubię, jak pytanie jest zadawane. Nie widzisz zbyt często takich pytań o uporządkowanej strukturze od nowych użytkowników. – MOnsDaR

+0

jeśli nie planujesz zmienić rozmiaru 2 tablic, możesz rzucić okiem na 'array_view' – sp2danny

Odpowiedz

44

Wpisz iteratory.

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()); 

Ponieważ zakresy iteracyjnej reprezentują pół otwarte zakresy [begin, end), nie trzeba dodać 1 do iteracyjnej sekund rozpocząć: lines.begin() + half_size nie jest kopiowany do pierwszego wektora.


Należy pamiętać, że takie rzeczy jak

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

nie są standardem C++ (i jako takie nie przenośne). Są to tak zwane macierze o zmiennej długości (w skrócie VLA) i są rzeczami C99. Niektóre kompilatory mają je jako rozszerzenie podczas kompilowania kodu C++ (GCC, Clang). Zawsze kompiluj z -pedantic, aby otrzymać ostrzeżenie. Te VLA działają modnie dla typów nie-POD i generalnie nie są przydatne, ponieważ nie można ich nawet zwrócić.

+0

Bardzo dobra odpowiedź +1 dla" nie musisz dodawać 1 do drugiego iteratora " –

2

Jeśli potrzebne jest tylko odniesienie do numerów bez ich manipulacji, to można zrobić:

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

tablica_1 i array_2 są, rzeczywiście, wskaźniki do początku i na środku wektorze. Działa to, ponieważ STL gwarantuje, że wektory przechowują swoje elementy w pamięci ciągłej. Należy zauważyć, że odwołanie do metody lines.begin() nie może być w tym przypadku użyte.

1

Jeżeli nie można użyć kodu z Xeo odpowiedź powodu surowych zasad kompilatora lub chcesz bardziej ogólny sposób, spróbuj 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()); 
Powiązane problemy