Лучший способ разделить вектор на два меньших массива?
что я пытаюсь сделать:
Я пытаюсь разделить вектор на два отдельных массива. Текущий вектор int содержит элемент на строку в текстовом файле. Текстовый файл представляет собой список случайных целых чисел.
Как я планирую это сделать:
моя текущая идея-создать два регулярных массива int, затем перебрать весь вектор и скопировать n / 2 элементы каждого из массивов.
что Я хотел бы знать:
каков самый элегантный способ выполнения моей задачи? У меня такое чувство, что я могу сделать это, не повторяя вектор несколько раз.
код:
#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;
}
спасибо :)
4 ответов
использовать итераторы.
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());
поскольку диапазоны итераторов представляют собой полуоткрытые диапазоны [begin, end)
, вам не нужно добавлять 1 ко второму итератору начала:lines.begin() + half_size
не копируется в первый вектор.
обратите внимание, что такие вещи, как
int split = lines.size() / 2;
int arrayA[split];
int arrayB[split];
не стандартный C++ (и не портативный). Это так называемые массивы переменной длины (VLAs для краткости) и являются вещью C99. Некоторые компиляторы имеют их как расширение при компиляции кода C++ (GCC, Clang). Всегда компилируйте с -pedantic
получить предупреждение. Эти VLAs действуют фанки для типов не-POD и обычно не полезны, так как вы даже не можете их вернуть.
Если вам нужна только ссылка на числа, не манипулируя ими, то вы можете сделать:
int *array_1 = &lines[0];
int *array_2 = &lines[lines.size() / 2];
array_1 и array_2 на самом деле являются указателями на начало и середину вектора. Это работает, поскольку STL гарантирует, что векторы хранят свои элементы в непрерывной памяти. Обратите внимание, что ссылаясь на строки.begin () нельзя использовать для этого.
Если вы не можете использовать код Xeo ответ из-за строгих правил компилятора или вы хотите более общий способ, попробуйте 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());
решение для разделения вектора на части с переменным числом с помощью итератора.
#include <iostream>
#include <vector>
int main()
{
// Original vector of data
std::vector<double> mainVec{1.2, 2.3, 3.4, 4.5, 5.6, 6.7, 7.8, 8.9, 9.0};
// Result vectors
std::vector<std::vector<double>> subVecs{};
// Start iterator
auto itr = mainVec.begin();
// Variable to control size of non divided elements
unsigned fullSize = mainVec.size();
// To regulate count of parts
unsigned partsCount = 4U;
for(unsigned i = 0; i < partsCount; ++i)
{
// Variable controls the size of a part
auto partSize = fullSize / (partsCount - i);
fullSize -= partSize;
//
subVecs.emplace_back(std::vector<double>{itr, itr+partSize});
itr += partSize;
}
// Print out result
for (const auto& elemOuter : subVecs)
{
std::cout << std::fixed;
for (const auto& elemInner : elemOuter)
{
std::cout << elemInner << " ";
}
std::cout << "\n";
}
}