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

Создание n-мерного динамического массива

21.11.2017, 21:40. Показов 6428. Ответов 55
Метки нет (Все метки)

Ломаю голову над реализацией функции, которая создаёт n-мерный динамический массив. Возможно ли это вообще?
Для меня проблема в количестве звёздочек, то есть сколько звёздочек у первого указателя, такая и размерность массива, но эти звёзочки просто так не поставишь.
Заранее спасибо за Ваши идеи и советы.
__________________
Помощь в написании контрольных, курсовых и дипломных работ, диссертаций здесь
0
Лучшие ответы (1)
Programming
Эксперт
94731 / 64177 / 26122
Регистрация: 12.04.2006
Сообщений: 116,782
21.11.2017, 21:40
Ответы с готовыми решениями:

Создание 3-х мерного динамического массива
Что-то туплю.. не могу сделать 3-х мерный динамический массив int *a;int q,n,r,v;int ***b;int...

Инициализация N-мерного динамического массива
Добрый день. Возникла идея написать функцию, которая инициализировала n-мерный динамический...

Постороить из 2 мерного массива в 1 мерный, который содержит все элементы 2 мерного массива , содержащихся по периметру массива
Постороить из 2 мерного массива в 1 мерный, который содержит все элементы 2 мерного массива ,...

Создание динамического массива
const int Num=5; const int SIZE=4096 * Num; SHORT Buf; как такое заменить, если Num-...

55
3503 / 2122 / 395
Регистрация: 09.09.2017
Сообщений: 8,787
21.11.2017, 22:05 2
Как и с двумерным - одна.
C
1
int *arr = (int*)malloc(sizeof(int)*N*N*N*N); //4-мерный массив
Обращение к элементу [i,j,k,l] идет как
C
1
arr[i + N*j + N*N*k + N*N*N*l]
если использовать макросы, можно упростить обращение
C
1
2
3
#define ARR(x,y,z,w) arr[x+N*(y+N*(z+N*w))]
ARR(1,2,3,4) = 5;
if(ARR(6,7,8,9) == 1){...}
В принципе, можно использовать new/delete в плюсовом стиле, но для базовых типов это преимущества не даст.
2
2 / 1 / 1
Регистрация: 28.10.2014
Сообщений: 122
22.11.2017, 01:41  [ТС] 3
Спасибо, можно ли реализовать это рекурсивным способом?
0
3503 / 2122 / 395
Регистрация: 09.09.2017
Сообщений: 8,787
22.11.2017, 09:52 4
реализовать рекурсивным способом что?
0
1463 / 1005 / 455
Регистрация: 30.10.2017
Сообщений: 2,793
22.11.2017, 10:06 5
но эти звёзочки просто так не поставишь
А в чем проблема?

C++
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
#include <iostream>
 
int main()
{
    int ***m = new int **[3];
 
    for (int i = 0; i < 3; i++)
    {
        m[i] = new int *[3];
 
        for (int j = 0; j < 3; j++)
        {
            m[i][j] = new int [3];
 
            for (int k = 0; k < 3; k++)
            {
                m[i][j][k] = i * 3 * 3 + j * 3 + k;
            }
        }
    }
 
    for (int i = 0; i < 3; i++)
    {
        for (int j = 0; j < 3; j++)
        {
            for (int k = 0; k < 3; k++)
            {
                std::cout << m[i][j][k] << std::endl;
            }
        }
    }
 
    system("pause");
    return 0;
}
0
2 / 1 / 1
Регистрация: 28.10.2014
Сообщений: 122
24.11.2017, 04:15  [ТС] 6
Просто получается для 18-мерного массива, например, придётся 18 звёздочек брать, поэтому я хотел бы реализовать его рекурсивное создание и спрашиваю участников киберфорума возможно ли создать рекурсивную функцию создания n-мерного массива.
0
Любитель чаепитий
3732 / 1791 / 562
Регистрация: 24.08.2014
Сообщений: 5,992
Записей в блоге: 1
24.11.2017, 06:25 7
Лучший ответ Сообщение было отмечено Валерий_ как решение

Решение

C++
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
#include <iostream>
#include <cassert>
 
template<typename T, size_t N>
struct NDimensionalArray
{ typedef typename NDimensionalArray<T, N - 1>::type * type; };
 
template<typename T> struct NDimensionalArray<T, 1>
{ typedef T * type; };
 
template<typename T>
void initializeNDimensionalArray(T &, size_t)
{}
 
template<typename T>
void initializeNDimensionalArray(T *& arr, size_t N)
{
    arr = new T[N];
    for (size_t it = 0; it < N; ++it)
        initializeNDimensionalArray(arr[it], N);
}
 
int main()
{
    typedef NDimensionalArray<int, 3>::type ThreeDimensionalArray;
    typedef NDimensionalArray<int, 2>::type TwoDimensionalArray;
    typedef NDimensionalArray<int, 1>::type OneDimensionalArray;
    
    static_assert(std::is_same<ThreeDimensionalArray, int***>::value, "three");
    static_assert(std::is_same<TwoDimensionalArray, int**>::value, "two");
    static_assert(std::is_same<OneDimensionalArray, int*>::value, "one");
    
    ThreeDimensionalArray arr;
    initializeNDimensionalArray(arr, 1);
    
    assert(arr != nullptr);
    assert(arr[0] != nullptr);
    assert(arr[0][0] != nullptr);
}
1
3503 / 2122 / 395
Регистрация: 09.09.2017
Сообщений: 8,787
24.11.2017, 08:46 8
Цитата Сообщение от Валерий_ Посмотреть сообщение
Просто получается для 18-мерного массива, например, придётся 18 звёздочек брать
Так чем вам не нравится вариант с одной звездочкой?
C
1
2
3
int *arr18 = (int*)malloc(sizeof(int)*pow(N,18));
...
free(arr18);
другое дело что массив 18-й степени вложенности это ИМХО перебор, тут уже пора исправлять алгоритм
0
Любитель чаепитий
3732 / 1791 / 562
Регистрация: 24.08.2014
Сообщений: 5,992
Записей в блоге: 1
24.11.2017, 09:40 9
Цитата Сообщение от COKPOWEHEU Посмотреть сообщение
Так чем вам не нравится вариант с одной звездочкой?
я не ТС, но обращение к массиву убогое.
на каждую вложенность надо делать макрос ARR1, ARR2, ..., ARRN или писать какие-то не интуитивно-понятные математические костыли.
зачем запирать себя в рамки, если язык позволяет сделать всё легче?
и да, если вы начнёте тут говорить про то, что в си нельзя такое реализовать нормально, то прошу обратить ваше внимание на раздел, в котором мы с вами находимся.
0
3503 / 2122 / 395
Регистрация: 09.09.2017
Сообщений: 8,787
24.11.2017, 10:38 10
Обращение к любому массиву с размерностью больше 5 убогое.
Вот и мне непонятно зачем писать неинтуитивные костыли из создания массивов массивов в цикле. Вы хоть сами попробуйте расписать создание хотя бы 5-мерного массива. А для обычного массива это никаких проблем не представляет:
C
1
2
3
4
int *arr = (int*)malloc(sizeof(int)*N*N*N*N*N);
if(!arr){printf("Error allocate memory\n" return 1;}
#define Arr(a0, a1, a2, a3, a4) arr[a0 + N*(a1 + N*(a2 + N*(a3 + N*a4)))]
free(arr);
Пытаться реализовать ваш вариант я даже пытаться не буду - боюсь даже представить какого размера это будет. Тем более с проверками успешности выделения памяти.
0
1463 / 1005 / 455
Регистрация: 30.10.2017
Сообщений: 2,793
24.11.2017, 11:23 11
Как вариант можете попробовать создать свой АТД с шаблоном для поддержки разных типов. В конструктор подаете размерность и размер массива. Перегружаете операцию индексации на работу с массивом индексов. Например

C++
1
2
3
4
5
MyArray<int> a(10, 3);
int myIndex[10] = {0, 0, 0, 0, 0, 0, 0, 0, 0, 2};
 
a[myIndex] = 5;
cout << a[myIndex] << endl;
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
24.11.2017, 11:33 12
А где тут конец рекурсии ?
C++
1
2
3
4
5
6
7
template<typename T>
void initializeNDimensionalArray(T *& arr, size_t N)
{
    arr = new T[N];
    for (size_t it = 0; it < N; ++it)
        initializeNDimensionalArray(arr[it], N);
}
0
Любитель чаепитий
3732 / 1791 / 562
Регистрация: 24.08.2014
Сообщений: 5,992
Записей в блоге: 1
24.11.2017, 11:48 13
Цитата Сообщение от Pechkin80 Посмотреть сообщение
А где тут конец рекурсии ?
в строке под номером 7.
0
Диссидент
Эксперт C
26948 / 16829 / 3698
Регистрация: 24.12.2010
Сообщений: 37,766
24.11.2017, 12:09 14
Валерий_, Если я правильно вас понял, речь идет о создании функции для работы с массивами с разными (заранее не известными) количествами измерений?
Основная идея изложена уважаемым COKPOWEHEU, в посте 2 - представить вашу чудовищную матрицу в виде линейного массива. А для вычисления индекса использовать цикл.
На вход такой функции подается количество измерений - К и небольшой массив размерностей int R[K].
Произвольный индекс также задается массивом int Ind[K]
Все не очень сложно даже на чистом Си. И без рекурсии.
Правда, 18-мерные массивы - это действительно круто! Даже если по каждому измерению размерность 2, объем массива получается 218
0
1463 / 1005 / 455
Регистрация: 30.10.2017
Сообщений: 2,793
24.11.2017, 12:31 15
GbaLog-, почему бы проверку памяти не добавить сразу после выделения памяти?

C++
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
#include <iostream>
#include <cassert>
 
template<typename T, size_t N>
struct NDimensionalArray
{
    typedef typename NDimensionalArray<T, N - 1>::type * type;
};
 
template<typename T> struct NDimensionalArray<T, 1>
{
    typedef T * type;
};
 
template<typename T>
void initializeNDimensionalArray(T &, size_t)
{}
 
template<typename T>
void initializeNDimensionalArray(T *& arr, size_t N)
{
    arr = new T[N];
    assert(arr != nullptr);
 
    for (size_t it = 0; it < N; ++it)
        initializeNDimensionalArray(arr[it], N);
}
 
int main()
{
    typedef NDimensionalArray<int, 18>::type EighteenDimensionalArray;
    //typedef NDimensionalArray<int, 3>::type ThreeDimensionalArray;
    //typedef NDimensionalArray<int, 2>::type TwoDimensionalArray;
    //typedef NDimensionalArray<int, 1>::type OneDimensionalArray;
 
    static_assert(std::is_same<EighteenDimensionalArray, int******************>::value, "eighteen");
    //static_assert(std::is_same<ThreeDimensionalArray, int***>::value, "three");
    //static_assert(std::is_same<TwoDimensionalArray, int**>::value, "two");
    //static_assert(std::is_same<OneDimensionalArray, int*>::value, "one");
 
    EighteenDimensionalArray arr;
    initializeNDimensionalArray(arr, 2);
 
    //assert(arr != nullptr);
    //assert(arr[0] != nullptr);
    //assert(arr[0][0] != nullptr);
 
    for (int i = 0; i < 2; i++)
    {
        arr[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i] = i;
        std::cout << arr[i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i][i] << std::endl;
    }
 
    system("pause");
    return 0;
}
Добавлено через 16 минут
Или это просто для демонстрации разного обращения к массиву было?
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
24.11.2017, 12:45 16
Не понимаю. Функция выделения памяти должна иметь три параметра 1 - тип 2 - размер 3 - размерность. Какието могут быть шаблонные , а какието нет, но три а не 2.
0
1463 / 1005 / 455
Регистрация: 30.10.2017
Сообщений: 2,793
24.11.2017, 12:54 17
Pechkin80, если про алгоритм от GbaLog-, то размерность задается рекурсией, а тип и размер указаны шаблоном T и значением N

C++
1
arr = new T[N];
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
24.11.2017, 12:57 18
QuakerRUS, Да я понял, что он хотел размерность задать рекурсией, только где условия её окончания ???
0
1463 / 1005 / 455
Регистрация: 30.10.2017
Сообщений: 2,793
24.11.2017, 13:02 19
Выложу и пример работы алгоритма от COKPOWEHEU

C++
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
#define arr(a0, a1, a2, a3, a4, a5, a6, a7, a8, a9, a10, a11, a12, a13, a14, a15, a16, a17) arr[a0 + N*(a1 + N*(a2 + N*(a3 + N*(a4 + N*(a5 + N*(a6 + N*(a7 + N*(a8 + N*(a9 + N*(a10 + N*(a11 + N*(a12 + N*(a13 + N*(a14 + N*(a15 + N*(a16 + N*a17))))))))))))))))]
#include <iostream>
 
int main()
{
    int N = 2;
 
    int *arr = (int*)malloc(sizeof(int)*N*N*N*N*N*N*N*N*N*N*N*N*N*N*N*N*N*N);
    if (!arr) { printf("Error allocate memory\n"); system("pause"); return 1; }
 
    for (int i = 0; i < 2; i++)
    {
        arr(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i) = i;
        std::cout << arr(i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i, i) << std::endl;
    }
 
    free(arr);
 
    system("pause");
    return 0;
}
0
21 / 19 / 7
Регистрация: 14.03.2014
Сообщений: 249
24.11.2017, 13:02 20
Или это просто концепция ? Типа сами додумывайте.
0
IT_Exp
Эксперт
87844 / 49110 / 22898
Регистрация: 17.06.2006
Сообщений: 92,604
24.11.2017, 13:02
Помогаю со студенческими работами здесь

Создание динамического массива
Первое задание помогите пожалуйста.

Создание динамического массива
Как ввести самому количество элементов массива,а не задавать константно ?

Создание динамического массива
Хотел написать программу, чтобы пользователь мог задать количество элементов в одномерном массиве,...

Создание динамического массива
объясните пожалуйста вот эту часть // sozdanie dinamicheskogo massiva m*n...


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

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

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