Tablice wielowymiarowe tworzone na tablicy jednowymiarowej

0

Zastanawiam się jak utworzyć tablicę trójwymiarową i większą korzystając z tablicy jednowymiarowej.

Dla dwuwymiarowej wygladałoby to mniej wiecej tak:

int * array = (int *) malloc(X * Y * sizeof(int));

i odwołanie poprzez

array[X*i+j]

Idea jest taka X to ilość wierszy, i to aktualny wiersz, a j to kolumna. Łatwo zauważyć, że przy tym mnożeniu mamy dla wiersza zerowego 0X + j(gdzie j to wartość od 0 do Y-1) dla wiersza pierwszego mamy 1X+j i widać, że to się nigdy nie będzie pokrywało.

I teraz nie bardzo moge dojść do tego jak właśnie w analogiczny sposób zrobić tablicę trójwymiarową(i większe). Zaalokować pamięć bardzo prosto...

int * array = (int *) malloc(X * Y * Z * sizeof(int));

ale jaką kombinacją odwoływać się do elementów. Na pewno nie działają kombinacje:

X*i+Y*j+k
X*Y*i+j+k
X*i*Y*J+k

Jeżeli ktoś ma pomysł, prosze o pomoc.

0

iYZ+j*Z+k

tylko sprawdź, bo nie wiem czy dobrze ułożyłem, powinno być dobrze

0

uniwersalnie (rozmiary kolejnych wymiarów: X,Y,Z,A, ... ; kolejne odpowiednie indeksy: i, j, k, l, m ):
( ( ( ( ... + m)*A + l)*Z +k)*Y+j)*X+i
jak masz mniej wymiarów to przyjmujesz odpowiednie indeksy jako zero i wzór się upraszcza.

Taka wersja z nawiasami szybciej się liczy (minimalizacja liczby mnożeń).

0

iYZ+j*Z+k

jest ok :)

( ( ( ( ... + m)*A + l)*Z +k)*Y+j)*X+i
nie działa, a nawet jeżeli to na pewno nie tak jak powinno :)

Może ktoś inny zna sposób uniwersalny(tj. wzór).

0

No nie działa, bo tak na oko to na pewno pierwszy wymiar (X) trzeba ze wzoru całkiem wywalić w cholerę ;) Ale to można sobie policzyć, jak już się zna ideę, a ma się siłę na zrobienie czegoś więcej, niż napisanie: "nie działa".

współrzędne X,Y,Z. Indeksy: i,j,k:
((k*Y + j)*Z + i

współrzędne A,B,C,D,E,...,M,N. Indeksy: n,m,...e,d,c,b,a (odwróciłem sobie kolejność indeksów, bo wzór uogólniony wygląda ładniej)

( (...( ( ( (aB+b)C+c )D+d )E+e )...+...)M+m )N+n

albo bez nawiasów. wprowadźmy sobie oszukańcze wyrażenie pomocnicze na iloczyn kolejnych wymiarów od A do N:
<br> \Pi^N_A = A \cdot B \cdot \cdot ... \cdot N<br>

no teraz współrzędne A,B,C,D,E,...,M,N. Indeksy: a,b,c,d,e,...,m,n (tym razem nie odwracam):

a\Pi<sup>N_B + b\Pi</sup>N_C + c\Pi<sup>N_D + d\Pi</sup>N_E + ... m\Pi^N_N + n
0
Ranides napisał(a)

No nie działa, bo tak na oko to na pewno pierwszy wymiar (X) trzeba ze wzoru całkiem wywalić w cholerę ;)
Tak na pewno to ty się tu mylisz. Pomyśl, gdzie powinna być pierwsza komórka drugiego rzędu? Zaraz po ostatniej komórce pierwszego rzędu, więc musi mieć indeks taki jak rozmiar pierwszego wymiaru. To ostatni wymiar nie ma znaczenia. Zresztą jak patrze na twoje wzory to ty napisałeś dokładnie to samo co ja.

0

Ale po co się kłócić... próbowałem z obiema wersjami i dalej mi coś nie chodzi ;/
(i prosze nie pisz mi, że nie próbowałem, bo próbowałem ale nie wyszło, gdyby mi wyszło to bym nie pisał)

oto kod...

 int X=5, Y=5, Z=2, W=5;
        int * c = (int *) malloc(X * Y * Z * W * sizeof(int));
    	c[X*1+1] = 4;
    	int s = 0;
        for(int i=0; i < X; i++){
                for(int j=0; j < Y; j++){
                        for(int k=0; k < Z; k++){
                                     for(int l=0; l < W; l++){
                                             //A,B,C,D,E,...,M,N. Indeksy: n,m,...e,d,c,b,a 
                                             //aB+b)C+c )D+d )E+e )...+...)M+m )N+n
                                             //i+W*(j+Z*(k+Y*l)) 
                                             c[i+W*(j+Z*(k+Y*l))] = s; // tak czy siak... tu sie sypie...
                                             printf("%d/", i+W*(j+Z*(k+Y*l)));
                                             s++;
                                }
                     }
                
                }
                printf("\n");
        }

        printf("\n\n");

         for(int i=0; i < X; i++){
                for(int j=0; j < Y; j++){
                        for(int k=0; k < Z; k++){
                                for(int l=0; l < W; l++){
                                       printf("%d-",c[i+W*(j+Z*(k+Y*l))]);
                                }
                        }
                }
        }

Nie wydaje mi się, żebym coś źle przepisał...

0

No w sumie nie ma co się kłócić, bo zamotać idzie się łatwo, jak to widzę w sumie :D I przeprosić też muszę, bo skoro zamotać się łatwo, to więcej pisać nie będę, że komuś się nie chce.

  1. spostrzeżenie luźne akademickie:
    Ok Marku, nie tyle się mylę, co liczyłem od drugiej strony, tzn: ty masz współrzędne (XYZA), w nawiasach kolejność AZYX, więc wywaliłeś ostatni wymiar. Ja w nawiasach mam kolejność XYZA, więc wywaliłem pierwszy wymiar.

Efekt jest taki, że któryś z nas liczy współrzędne tak jak kompilator, a ktoś na odwrót. Nie mam pojęcia który. Przyjmijmy, że ty - bo mi się merda ;)

  1. Praktyka:
    Żeby nie teoretyzować, bo zadanie trywialne, a się motam jak gimnazjalista... isso, musisz granice w forach zamienić:
#include <iostream>
using namespace std;

int main() {
    const int A=2, X=A;
    const int B=3, Y=B;
    const int C=4, Z=C;
    const int D=5, W=D;

    // tablicę niech poukłada kompilator, żebyśmy widzieli,
    // jak nasze indeksowanie się ma do niego
    int array1[A][B][C][D];
    int array2[A][B][C][D];
    // i rzutujmy obszar tablicy na wskaźnik
    int* memory1 = (int*)array1;
    int* memory2 = (int*)array2;


    // wypełnienie chyba Marka (ijkl - WZYX):
    int n1=100;
    for(int i=0; i < W; i++)
    for(int j=0; j < Z; j++)
    for(int k=0; k < Y; k++)
    for(int l=0; l < X; l++)
        // wzór ijkl - WZY(X)
        memory1[ i+W*(j+Z*(k+Y*l)) ] = n1++;

    // wyświetlenie
    // ułożenie danych ?tak jak? kompilatora
    // dlatego pętla leci zmiennymi d,c,b,a
    for(int d=0; d<D; d++)
    for(int c=0; c<C; c++)
    for(int b=0; b<B; b++)
    for(int a=0; a<A; a++)
        cout << array1[a][b][c][d] << " ";
    cout << endl;

    // wypełnienie chyba "moje" (zmienne abcd - ABCD)
    int n2=100;
    for(int a=0; a<A; a++)
    for(int b=0; b<B; b++)
    for(int c=0; c<C; c++)
    for(int d=0; d<D; d++)
        // wzór abcd - (A)BCD
        memory2[ ((a*B+b)*C+c)*D+d ] = n2++;


    // wyświetlenie
    // ułożenie danych ?odwrotnie? niż kompilatora
    // dlatego pętla leci zmiennymi a,b,c,d
    for(int a=0; a<A; a++)
    for(int b=0; b<B; b++)
    for(int c=0; c<C; c++)
    for(int d=0; d<D; d++)
        cout << array2[a][b][c][d] << " ";
    cout << endl;


    return 0;
    }

1 użytkowników online, w tym zalogowanych: 0, gości: 1