2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
1

Создать тройной вложенный вектор

17.10.2019, 16:46. Показов 2852. Ответов 19

Добрый день

Подскажите, пожалуйста, как создать тройной вложенный вектор?
И как его обнулять?

К примеру с двойным вектором все понятно:
C++ (Qt)
1
2
3
4
5
6
7
std::vector<std::vector<std::uint8_t>> m_vec;
m_vec.resize(100,   std::vector<std::uint8_t>(100, 0));
for (std::size_t index = 0; index < 100; index++ )
            {
                m_vec[index].resize(100 0);
                m_vec[index].assign(m_vec[index].size(), 0);
            }
Как сделать аналогичное для
C++ (Qt)
1
std::vector<std::vector<std::vector<std::uint8_t>>> m_vec;
?

Можно конечно сделать аналогично, или по принципу массива (с перемножением индексов), но получается уж больно громоздко как-то. Может есть способы сделать проще?

Добавлено через 11 минут
У меня получается как-то так сейчас:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
m_vector.resize(100, std::vector<std::vector<std::uint8_t>>(100, std::vector<std::uint8_t>(100,0)));
            for (std::size_t index_h = 0; index_h < static_cast<uint16_t>(100); index_h++ )
            {
                m_vector[index_h].resize(100, std::vector<std::uint8_t>(100,0));
                for (std::size_t index_m = 0; index_m < static_cast<uint16_t>(100); index_m++ )
                {
                    m_vector[index_h][index_m].resize(100, 0);
                    m_vector[index_h][index_m].assign(m_vector[index_h][index_m].size(), 0);
                }
            }
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
17.10.2019, 16:46
Ответы с готовыми решениями:

Класс "вектор" с конструкторами, позволяющими создать нулевой вектор и вектор с произвольным числом элементов
Привет! Задача следующая. Нужно реализовать класс &quot;вектор&quot; с конструкторами, которые позволяют...

Создать иерархию классов вектор и безопасный вектор с проверкой выхода за пределы
Создать иерархию классов вектор и безопасный вектор с проверкой выхода за пределы. Безопасный...

Создать иерархию классов вектор(longint) и безопасный вектор с проверкой выхода за пределы
Помогите не знаю как сделать! Создать иерархию классов вектор(longint) и безопасный вектор с...

Создать классы "Вектор" и "Матрица", реализовать умножение матрицы на вектор
Создать классы «Вектор (Строка, столбец)» и «Матрица». Реализовать умножение матрицы на вектор. я...

19
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
17.10.2019, 17:45 2
C++
1
2
    //объявляем куб 100*100*100, заполняем нулями
    std::vector<std::vector<std::vector<uint8_t>>> m_vec{100,{100,std::vector<uint8_t>(100,0)}};
или так
C++
1
2
3
4
5
6
7
    using td_lineX=std::vector<uint8_t>;
    using td_surfYX=std::vector<td_lineX>;
    using td_cube=std::vector<td_surfYX>;
 
    size_t n=5;
    //объявляем куб n*n*n, заполняем значением 2
    td_cube m_vec(n,td_surfYX(n,td_lineX(n,2)));
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
17.10.2019, 17:57  [ТС] 3
Алексей1153, Это создание.
А resize как делать? Если периодически размеры нужно менять?

Т.е. просто создать то не проблема.
Хочется как раз объявить без определения размеров, а потом уже при ресайзе их задавать.
0
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
17.10.2019, 18:07 4
Leardjiny, пишешь класс-оболочку с методами, который делает всё нужное

Добавлено через 6 минут
вообще, я бы такой многомерный массив в классе объявил бы как


private:
std::vector<uint8_t> vec;
size_t N=0;


сделал бы метод, задающий длину этого вектора N*N*N (ну и хранить само значение N неплохо бы, чтобы помнить, какой размер был задан)

+сделал бы метод получения ссылки по координатам x,y,z
+остальные методы
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
17.10.2019, 18:10  [ТС] 5
Алексей1153, ну да, это самый очевидный вариант. Просто хотелось бы избавиться от вычислений индексов.
Хотя в целом можно и так тоже сделать
0
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
17.10.2019, 18:18 6
Leardjiny, зато по производительности и сжиранию памяти - самый шустрый вариант
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
18.10.2019, 15:42  [ТС] 7
Алексей1153, Наверное да, Вы правы - возможно получше чем тройные индексы делать
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 14:32  [ТС] 8
Сделал так:

C++ (Qt)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
template <typename T>
class vector4d {
public:
    vector4d(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0, T const & t=T()) :
        m_d1(d1), m_d2(d2), m_d3(d3), m_d4(d4)
    {
        size_t size = 1;
        if (d1 != 0)
            size *= d1;
        if (d2 != 0)
            size *= d2;
        if (d3 != 0)
            size *= d3;
        if (d4 != 0)
            size *= d4;
        m_data.resize(size, t);
        m_data.assign(size, t);
    }
 
    T & operator()(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0) {
        return m_data[d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4];
    }
 
    T const & operator()(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0) const {
        return m_data[d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4];
    }
 
    void resize(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0, T val = 0)
    {
        m_d1 = d1;
        m_d2 = d2;
        m_d3 = d3;
        m_d4 = d4;
        size_t size = 1;
        if (d1 != 0)
            size *= d1;
        if (d2 != 0)
            size *= d2;
        if (d3 != 0)
            size *= d3;
        if (d4 != 0)
            size *= d4;
        m_data.resize(size, val);
        m_data.assign(size, val);
    }
 
    T getValue(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0)
    {
        return m_data[d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4];
    }
 
    void setValue(size_t d1=0, size_t d2=0, size_t d3=0, size_t d4=0, T val = 0)
    {
        m_data[d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4] = val;
    }
 
    bool CheckArrayLimits(const char* location, size_t d1, size_t d2, size_t d3, size_t d4)
    {
        size_t index = d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4;
        if (index >= m_data.size())
        {
            qDebug() << location << " DopplerFilter error: wrong index for 4d vector: " << index << "" << m_data.size();
            return false;
        }
 
        return true;
    }
 
private:
    size_t m_d1,m_d2,m_d3, m_d4;
    std::vector<T> m_data;
};

Подскажите, пожалуйста. Как будет быстрее и проще обращаться к элементам массива, и записывать их?
Просто текущий вариант работает быстрее чем vector<vector<vector>>>, но тоже медленно.

Есть подозрение, что чтение и запись через getValue и setValue - не самый быстрый способ.
Может напрямую обращаться?

что-нибудь в стиле:

C++ (Qt)
1
2
3
4
vector4d<int> myVec;
myVec.resize(100,100,100,100,0);
int a = myVec(10,10,10,10);
a = a+1;
Правда не уверен насчет корректности реализации, и насчет записи сомнения есть - как лучше сделать?
0
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
23.10.2019, 14:49 9
Leardjiny, можно возвращать ссылку на элемент, а не значение элемента. Только надо учитывать, что ссылка будет невалидна, если произойдёт изменение размера вектора.

У тебя оператор () как раз ссылку возвращает

Кстати, resize перед assign не нужен, последний сам устанавливает размер

Добавлено через 2 минуты
название для твоего класса не подходит, это же не вектор 4D, а гиперкуб ))
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 15:20  [ТС] 10
Алексей1153, Т.е. второй вариант, что я написал - в теории быстрее должен быть?

Просто я его попробовал, но прироста как-то особо не заметил. Не могу понять где слабое место
0
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
23.10.2019, 15:25 11
Leardjiny,

второй - это какой?

как измерял скорость работы ?

также - в релизе или в дебаге ?
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 15:41  [ТС] 12
Алексей1153,

Цитата Сообщение от Алексей1153 Посмотреть сообщение
второй - это какой?
пробовал так:

C++ (Qt)
1
2
3
4
5
6
7
8
9
for (i=0; i < 100; i++)
for (j=0; j < 100;j++)
for (k=0; k < 100; k++)
for (l=0; l < 100; l++)
{
int val = myVec.getValue(i,j,k,l);
val = val*10;
myVec.setValue(i,j,k,l,   (myVec.getValue(i,j,k,l) + val) );
}
И пробовал такой вариант (со скобками, как Вы и сказали):
C++ (Qt)
1
2
3
4
5
6
7
8
9
for (i=0; i < 100; i++)
for (j=0; j < 100;j++)
for (k=0; k < 100; k++)
for (l=0; l < 100; l++)
{
int val = myVec(i,j,k,l);
val = val*10;
 myVec(i,j,k,l) =  myVec(i,j,k,l) + val;
}
Цитата Сообщение от Алексей1153 Посмотреть сообщение
как измерял скорость работы ?
МОжно было время замерить конечно, но пока смотрел на загрузку.
Т.е. в принципе у меня идет чтение из файла, операция со считанным значением и ячейкой из массива, затем сохранение результата в эту же ячейку (примерно как в примере).
Только размеры массива не по 100, а несколько больше.

Т.е. задавал какое-то фпс для чтения, и смотрел реальную скорость обработки.
К примеру хотел читать со скоростью 1000фпс из файла, а получал только ~600.
Естественно что значение не стабильно держалось, а немного прыгает, но в среднем для обоих методов - одинаково вышло.


Цитата Сообщение от Алексей1153 Посмотреть сообщение
также - в релизе или в дебаге ?
Я в qtCeator делаю. Там запускаю релиз с отладкой
0
фрилансер
4166 / 3577 / 796
Регистрация: 11.10.2019
Сообщений: 9,613
23.10.2019, 15:48 13
Leardjiny, если нужно произвести одну операцию со всеми эелементами вектора, то не нужно делать 4 влуженных цикла, достаточно одного цикла. Вектор то один внутри

Про релиз и дебаг - я имею в виду, что релизная версия экзешника будет работать быстрее дебажной
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 16:01  [ТС] 14
Алексей1153,
Цитата Сообщение от Алексей1153 Посмотреть сообщение
если нужно произвести одну операцию со всеми эелементами вектора, то не нужно делать 4 влуженных цикла, достаточно одного цикла. Вектор то один внутри
Там в том и суть, что циклы вложенные нужны, т.к. в теле первого цикла сначала некоторые действия выполняются, перед тем как вызывается вложенный цикл. И т д для каждого цикла.


Цитата Сообщение от Алексей1153 Посмотреть сообщение
как измерял скорость работы ?
Измерил по времени в микросекундах сейчас, абсолютно одинаково для обоих вариантов.


Цитата Сообщение от Алексей1153 Посмотреть сообщение
Про релиз и дебаг - я имею в виду, что релизная версия экзешника будет работать быстрее дебажной
Я так и понял, запускаю релиз
0
686 / 298 / 97
Регистрация: 04.07.2014
Сообщений: 834
23.10.2019, 16:11 15
Цитата Сообщение от Leardjiny Посмотреть сообщение
Т.е. в принципе у меня идет чтение из файла,
Это как раз может быть узким местом. Для таких объёмов стоит сразу забить на текстовые форматы. И смотреть в сторону форматов поддерживающих сжатие. Возможно, HDF5.
Для боле быстрого заполнения, можно вынести метод T* data() из вектора.
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 16:19  [ТС] 16
AlexVRud, Там проблема не в чтении, я проверил все - вроде шустро работает, кроме момента с доступом по массиву.
На самом деле раньше был трехмерный массив и все работало быстро. Но когда еще одну размерность добавил - все сразу замедлилось.

Цитата Сообщение от AlexVRud Посмотреть сообщение
Для боле быстрого заполнения, можно вынести метод T* data() из вектора.
Объясните, пожалуйста - не совсем понял.
0
686 / 298 / 97
Регистрация: 04.07.2014
Сообщений: 834
23.10.2019, 16:28 17
http://www.cplusplus.com/refer... ctor/data/
если числа в файле хранятся в том же порядке, что и в векторе, то их можно просто писать
C++
1
2
3
4
5
auto A = vector4d<double>(N,M,K,L);
double *d = A.data();
for(size_t i=0; i<N*K*L*M; ++i) {
  d[i] = /*...*/;
}
Цитата Сообщение от Leardjiny Посмотреть сообщение
Но когда еще одну размерность добавил - все сразу замедлилось.
А размер изменился? Файловая подсистема ОС может кешировать недавно открытые файлы.
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
23.10.2019, 16:48  [ТС] 18
Цитата Сообщение от AlexVRud Посмотреть сообщение
если числа в файле хранятся в том же порядке, что и в векторе, то их можно просто писать
А, я понял. Тут речь не о заполнении, заполнение - это как раз инициализация по сути у меня.
Т.е. получаю данные, закидываю в массив, а затем обрабатываю уже.
Чтение и запись в массив - быстро проходят, а вот обработка из-за увеличившегося массива стала дольше. Хотя по сути единственное что изменилось - то что массив стал больше и запрос к нему стал чаще, но запрос только для чтения числа и записи.

Цитата Сообщение от AlexVRud Посмотреть сообщение
А размер изменился? Файловая подсистема ОС может кешировать недавно открытые файлы.
Размер входных данных - нет, только массива.

Если более точно, то к примеру у меня был массив 100х100х100.
Для каждой ячейки выполнялись какие-то действия и получалось несколько значений, к примеру тоже 100 штук. Я в ходе вычислений их анализировал ( к примеру для каждого значения результат true/false).
Потом из 100 значений true/false я получал какое-то одно (операцией | ).
После чего забирал из массива (100х100х100) значение, сравнивал с текущим результатом и записывал обратно новое значение.

Сейчас я решил делать все то же самое, но хранить не один результат по 100 значениям, а результат для каждого.
Соответственно массив стал 100х100х100х100, операции остались теми же.
Но к массиву я обращаюсь уже не после 100 вычислений, а после каждого вычисления - так же беру значение, сравниваю с результатом, и пишу новое.

По сути это все изменения в коде. В плане чтения и прочего - ничего не менялось.
0
686 / 298 / 97
Регистрация: 04.07.2014
Сообщений: 834
23.10.2019, 18:46 19
Во-первых сложно сказать, что утебя изменилось в алгоритме. Минимум у тебя в 100 раз больше данных. Во сколько раз увеличилась "трудоёмкость алгоритма" уже сложно сказать в 100, 100000, ... раз.
Так же стоит понимать, что на таких объёмах элементы A(i,j,k,l) и A(i+1,j,k,l) находятся далеко, возможно стоит переиграть порядок хранения индексов (поиграйся с m_data[d1*m_d2*m_d3*m_d4 + d2*m_d3*m_d4 + d3*m_d4 + d4]), но это не так сильно должно напрягать.
0
2 / 2 / 0
Регистрация: 22.09.2013
Сообщений: 217
24.10.2019, 12:04  [ТС] 20
Цитата Сообщение от AlexVRud Посмотреть сообщение
Во-первых сложно сказать, что утебя изменилось в алгоритме. Минимум у тебя в 100 раз больше данных.
В алгоритме ничего не изменилось, и данных ровно столько же.
Просто раньше я в вектор клал результат по каждым 100 числам (ну и забирал этот результат для сравнения).
А сейчас для каждого числа забираю и кладу.

Т.е. раньше обращение в вектор было каждые сто итераций на чтение/запись, а сейчас каждую итерацию. Но в самом алгоритме не изменилось ничего. Хотя производительность просела раза в 4-5 почему-то

Добавлено через 10 минут
Цитата Сообщение от AlexVRud Посмотреть сообщение
возможно стоит переиграть порядок хранения индексов
Вот над этим стоит подумать, с одной стороны я иду индексами, а не итераторами, и они вычисляются каждый раз заново, так что это по идее не должно роли играть.
С другой стороны - да, у меня в некоторых местах индексы не по порядку обращения как раз идут (т.е. инкрементируется как раз d2, а не d4).
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.10.2019, 12:04
Помогаю со студенческими работами здесь

Создать класс - вектор
Создать класс - вектор, который имеет в закрытой части указатель на данные целого типа и количество...

Создать вектор классов
у меня имеется класс с конструктором мне необходимо создать несколько объектов этого класса, так...

Создать класс – вектор
Помогите решить задачу... Создайте класс – вектор (в пространстве Rn ). Класс должен содержать...

Создать 2 указателя на вектор
хотел создать 2 указателя на вектор, а не получается... пишу: shared_ptr&lt;vector&lt;int&gt;&gt; ptr1 (new...


Искать еще темы с ответами

Или воспользуйтесь поиском по форуму:
20
Ответ Создать тему
Опции темы

КиберФорум - форум программистов, компьютерный форум, программирование
Powered by vBulletin
Copyright ©2000 - 2022, CyberForum.ru