Как объединить массивы на c++?
Пытался конактенировать, объединить массивы, но ничерта не разбираюсь в памяти C++, не знаю как просто склеить два динамических массива, никто не может подсказать или привести качественный пример?
- Вопрос задан более трёх лет назад
- 3392 просмотра
- Вконтакте
Вам нужно выделить новый массив размер которого = размер_массива_1 + размер_массива_2, а после скопировать в него данные по очереди из 1го и из 2го.
В вашем коде в функции push создаются новые массивы:
и эти массивы видны только до конца функции push, а оригинальные вы не трогаете вообще, а только освобождаете по ним память.
Как объединить два массива в C#?
вы можете написать метод расширения:
затем:
Я остановился на более универсальном решении, которое позволяет объединять произвольный набор одномерных массивов одного и того же типа. (Я объединял 3+ одновременно.)
функции:
и использование:
вы можете взять ToArray() call off the end. Есть ли причина, по которой вам нужно, чтобы это был массив после вызова Concat?
вызов Concat создает итератор над обоими массивами. Он не создает новый массив, поэтому вы не использовали больше памяти для нового массива. Когда вы вызываете ToArray, вы фактически создаете новый массив и занимаете память для нового массива.
Так что если вам просто нужно легко перебирать оба, то просто вызовите Concat.
Я знаю, что ОП был только слегка любопытно о производительности. Что большие массивы могут получить другой результат (см. @kurdishTree). И что это обычно не имеет значения (@Иордании.народный.) Тем не менее, мне было любопытно, и поэтому я потерял рассудок ( как объяснял @TigerShark). Я имею в виду, что я написал простой тест, основанный на исходном вопросе. и все ответы.
результат:
ролл свои собственные победы.
будьте осторожны с Concat метод. Пост объединение массивов в C# поясняет, что:
будет неэффективно для больших массивов. Это означает Concat метод предназначен только для массивов размера meduim (до 10000 элементов).
более эффективно (быстрее) использовать Buffer.BlockCopy over Array.CopyTo ,
Я написал простую тестовую программу ,которая «разогревает дрожание», скомпилированную в режиме выпуска и запустила ее без отладчика, подключенного к моей машине.
для 10,000,000 итераций примера в вопросе
функция concat взял 3088ms
копировать, чтобы взял 1079ms
BlockCopy взял 603ms
если я изменяю тестовые массивы на две последовательности от 0 до 99, то я получаю результаты, подобные этому,
функция concat взял 45945ms
копировать, чтобы взял 2230ms
BlockCopy взял 1689ms
из этих результатов я могу утверждать, что CopyTo и BlockCopy методы значительно более эффективны, чем Concat и кроме того, если производительность является целью, BlockCopy имеет значение CopyTo .
чтобы предупредить этот ответ, если производительность не имеет значения, или будет несколько итераций, выберите метод, который вы найдете проще всего. Buffer.BlockCopy предлагает некоторую утилиту для преобразования типов за пределами этого вопроса.
вы можете сделать это, как вы упомянули, или если вы хотите получить действительно инструкцию об этом вы можете свернуть свой собственный цикл:
наиболее эффективной структурой с точки зрения ОЗУ (и ЦП) для хранения объединенного массива будет специальный класс, который реализует IEnumerable (или, если вы хотите, даже происходит от массива) и внутренне связывается с исходными массивами для чтения значений. Насколько мне известно, функция concat делает именно это.
в вашем примере кода Вы можете опустить .ToArray () хотя, что сделало бы его более эффективным.
вам нужно помнить, что при использовании LINQ вы используете отложенное выполнение. Другие методы, описанные здесь, все работают отлично, но они выполняются немедленно. Кроме того, функция Concat (), вероятно, оптимизирована таким образом, что вы не можете сделать это самостоятельно (вызовы внутренних API, вызовы ОС и т. д.). В любом случае, если вам действительно не нужно пытаться оптимизировать, вы в настоящее время находитесь на своем пути к «корню всего зла» 😉
Я нашел элегантное решение одной линии с помощью LINQ или лямда — выражение, оба работают одинаково (LINQ преобразуется в лямбда при компиляции программы). Решение работает для любого типа массива и для любого количества массивов.
С помощью LINQ:
С Помощью Лямбда:
Я предоставил оба для своих предпочтений. Производительность мудрый @Сергей Штейн или @deepee1 это!—4—> решения немного быстрее, лямбда-выражение является самым медленным. Затраченное время зависит от типа(ов) элементов массива, но если нет миллионов вызовов, нет существенной разницы между методами.
извините, чтобы возродить старую нить, но как насчет этого:
тогда в вашем коде:
пока ты не позвонишь .ToArray() , .ToList() или .ToDictionary(. ) , память не выделена, вы можете «построить свой запрос» и либо вызвать один из этих трех, чтобы выполнить его, либо просто пройти через них все с помощью foreach (var i in z) <. >предложение, которое возвращает элемент одновременно из yield return t; выше.
вышеуказанную функцию можно сделать в расширение как следует:
так в коде, вы можете сделать что-то вроде:
остальное то же самое, что и раньше.
еще одно улучшение к этому будет меняться T[] на IEnumerable<T> (т. е. params T[][] станет params IEnumerable<T>[] ), чтобы эти функции принимали больше, чем просто массивы.
надеюсь, что это помогает.
для int[] то, что вы сделали, выглядит хорошо для меня. astander это ответ также будет хорошо работать для List<int> .
Как соединить два массива в С++
Вот такой код. При выполнении ввожу: 5, (1,2,3,4,5), 5 (6,7,8,9,10), получаю -858993460 -858993460 -858993460 -858993460 -858993460 1 2 3 4 5. Почему появляются эти «-858993460»? Я так понимаю проблема в памяти, но как ее решить?
Сделайте, например, так:
![]()
Во первых ваши массивы обьявлены с конкретным размером 5 , а вы вводите количество обрабатывемых элементов. Какая гарантия, что вы не вводите число больше чем 5?
Во вторых после цикла:
переменная k примет значение size2 , но вы выполняете:
Какая смысль в переменной J, непонятно. Фактически вы присваиваиваете элементу merge[size2] и последующим элементам значения из второго массива, а остальные остаются неинициализированными
![]()
Fswt, Вы указали в тегах C++, и даже используете объекты std::cin , std::cout , но почему Вы не хотите в полной мере использовать стандартную библиотеку для решения Ваших задач?
Я позволю себе сделать Вам несколько замечаний и предложу некоторые правки. Использовать их или нет — на Ваше усмотрение.
- Вы используете массивы фиксированной длинны, какой тогда смысл запрашивать у пользователя их размер? Если использование массивов не является обязательным условием Вашего задания, используйте std::vector .
- Вы одновременно используете cin , cout , операторы ввода-вывода и здесь же — scanf_s . Это функция точно не определена в стандарте C++, и ее наличие в библиотеке скорее всего опционально.
Предположим, что Вы согласились использовать вектор. Тогда можно реализовать ф-ию, которая будет читать данные из стандартного ввода и «складывать» их в массив:
std::copy — это обобщенный алгоритм для копирования элементов из одного диапазона в другой, std::back_inserter — функция для создания адаптера итератора вставки, которая получает на вход контейнер и генерирует выходной итератор.
Однако, если Вы попытаетесь использовать данную функцию в таком виде, как она реализована на данный момент, у Вас ничего не получится — нажатие клавиши Enter не прервет процесс чтения потока и, соответственно, он продолжится до тех пор, пока не будет сгенерирован сигнал (при условии, что Вы вводите данные с консоли) или не произойдет ошибка при чтении потока.
Условимся, что процесс чтения данных с потока должен быть прекращен по нажатию клавиши Enter, тогда нам нужно внести некоторые изменения в реализацию функции processInput :
Это вспомогательная функция, назначение которой — сформировать строковый поток ввода, который в дальнейшем и будет использоваться для чтения данных:
Для объеденения array_a и array_b Вы можете воспользоваться функцией std::merge :
C++ для начинающих Массивы Склеить два одномерных в оди
=====================
#include <iostream.h>
//ФУНКЦИЯ ЗАПОЛНЕНИЯ МАССИВА
void Fill (int * Arr ,int N )
<
for (int i = 0 ; i < N ; i ++) Arr [ i ]= i ;
>
//ФУНКЦИЯ ВЫВОДА МАССИВА НА ЭКРАН
void Show (int * Arr ,int N )
<
for (int i = 0 ; i < N ; i ++) cout << Arr [ i ]<< ” “ ;
cout << endl ;
>
int main ()
<
int N = 3 ; //Размер первого массива
int M = 11 ; //Размер второго массива
int * a =new int [ N ]; //Выделение памяти под первый массив
int *b=new int [ M ]; //Выделение памяти под второй массив
int * Arr =new int[ N+M ]; //Выделение памяти под итоговый массив
Fill ( a , N ); //Заполнение первого массива
Fill ( b , M ); //Заполнение второго массива
//ДВЕ СТРОЧКИ СКЛЕИВАЮТ ДВА МАССИВА В ИТОГОВОМ
memcpy ( Arr , a , N *sizeof(int)); //Копирование в итог данных из первого массива
memcpy ( Arr + N , b , M *sizeof(int)); //Копирование в конец итогового данных второго массива
Show ( a , N ); //Отображаем первый массив
Show ( b , M ); //Отображаем второй массив
Show ( Arr , N + M ); //Отображаем склеенный массив
delete [] Arr ; //Освобождения памяти
delete [] b ;
delete [] a ;
return 0 ;
>
=====================
В принципе, код небольшой, а, значит, рассказывать почти нечего. Кроме функций заполнения и вывода значений массивов на экран, выделения, освобождения памяти, основное решение укладывается в две строки. В обоих случаях в приведенном примере используется memcpy . Чтобы копировать один массив не в начало другого, а с какой-то позиции этого другого массива, использован прием арифметики указателей. (сложение обозначает перейти к следующему адресу)