V programih podatki pogosto ne nastopajo enorazsežno (npr. zaporedje števil), temveč v več razsežnostih. Bodisi gre pri tem za več poskusov z večimi meritvami, poljubno tabelarično obdelavo podatkov, izvajanje matričnih operacij, obdelovanje ravninskih slik....,ali nek podoben primer. V takih primerih je zaželeno imeti podatkovno strukturo, ki se po potrebi lahko širi preko večih dimenzij.
Java v osnovi ne pozna termina 'večrazsežna tabela' oz. naravno ne pozna take podatkovne strukture. Vendar :
Zgornje trditve držijo, tabelo int[][] tab; lahko potemtakem pojmujemo kot dvorazsežno tabelo celoštevilskih vrednosti
Kot je bilo v uvodu nakazano, večrazsežno tabelo deklariramo kot tabelo referenc. Tako
int[][] tab2D;
predstavlja 'deklaracijo' dvodimenzijske tabele
int[][][] tab3D;
tridimenzijske in
int[][][][] tab4D;
deklaracijo štirirazsežne tabele celih števil.
Samo tabelo podobno kot enorazsežno ustvarimo z operatorjem new :
tab2D = new int [2][2];tab3D = new int[7][9][2];tab4D = new int[2][3][2][3];
opazimo, da smo operatorju new podali toliko razsežnosti, kolikor razrežna je tabela, ki jo želimo ustvariti.
Po rezervaciji pomnilnika so vsi elementi tabele avtomatično inicializirani z vrednostjo 0 (ali ustrezno 0, če gre za tabele elementov drugačnih kot številskih tipov).
Vprašanje, ki se ponavadi zastavlja pri velikem številu dimenzij je, koliko je tisto največje število razsežnosti, ki ga je še smiselno uporabiti. Odgovor je seveda preprost : toliko, kolikor jih lahko programsko obvladujemo. Mimogrede. Java omejuje tako velikost dimenzije kot tudi število dimenzij z velikostjo celoštevilskega podatka.
Vendar je pri tem potrebno pomisliti tudi na trošenje pomnilnika vsled uporabe velikega števila razsežnosti:
in ponavadi element tabele ni celoštevilska vrednost, temveč celoten objekt, ki lahko zaseda nekaj 1000 zlogov pomnilnika ...
Kakorkoli že, v večini primerov se izkaže, da je običajna še obvladljiva razsežnost tabele 3 (živimo v 3D svetu, več razsežnosti si težko predstavljamo, ...)
Poglejmo si primer dvorazsežne tabele Ar velikosti 3 krat po 2 elementa :
in še logična predstavitev iste tabele :
(ustvarjanje tabele)
Rezervacija pomnilnika za elemente tabele dejansko ustvari tabelo (objekt) v pomnilniku. Tabelo ustvarimo z uporabo operatorja new, kot smo to počeli v primeru enorazsežnih tabel.
Zaradi same narave (zdradbe) večrazsežnih tabel, pa sta možna 2 načina (pristopa) k kreiranju tabele :
je najpreprostejši način rezervacije pomnilnika in pri njem praktično ne moremo storiti nobene napake. Torej tak način rezervacije lahko smatramo za varen način. Slabost postopka je v tem, da so vse tako ustvarjene tabele 'pravokotnih' oblik (število vrstic x število stolpcev) :
Ker je npr. dvorazsežna tabela zgolj tabela referenc na tabele elementov lahko rezervacijo izvedemo postopoma :
V nadaljevanju bomo skušali zgraditi enako strukturo, kot jo zgradi int[][] in2D = new int[3][5]; :
Slabost postopnega kreiranja je dolgotrajnosti njegovega postopka, saj zahteva kar nekaj programskih korakov in kaj lahko se nam zgodi, da katero izmed dimenzij pozabimo kreirati.
Dobra stran tega postopka pa je, da nam omogoča kreirati le tiste dimenzija, ki jih v danem trenutku potrebujemo, ter da konec koncev lahko ustvarimo tabelo, pri kateri vse dimenzije niso enake !
(indeksiranje)
Pri naslavljanju enorazsežnih tabel smo podali zaporedno številko (indeks) elementa, ki smo ga želeli nasloviti. Ker indeksa v programski kodi ne moremo pisati na matematični način, podajamo njegovo vrednost pri naslavljaju znotraj oglatih oklepajev.
Zelo podobno je pri večdimenzijskih tabelah. Razlika nastopa le v tem, da je naslovljeni element v taki tabeli dejansko na preseku vseh možnih dimenzij tabele; torej ima toliko indeksev, kot je dimenzija same tabele v kateri element naslavljamo.
Primer je podan za tabelo dimenzij 3 x 2, ki si jo logično predstavljamo kot tabelo treh vrstic (prva dimenzija, prvi indeks) in dveh stolpcev (druga dimenzija, drugi indeks) :
V primeru, da bi podali le en indeks, bi to bil avtomatično indeks 'vrstice'; to pa pomeni, da ne bi naslovili števila, temveč celotno vrstico ('vrstica' je v pomnilniški predstavitvi referenca na tabelo dveh celih števil).
Predhodno smo omenili, da s postopkom postopnega kreiranja tabele lahko ustvarimo tabelo, pri kateri vse dimenzije niso enako velike. Primer take tabele predstavlja tab :
Primer rezervacije z inicializacijo :
Kot vsak drug referenčnega tipa, lahko tudi tabelo odstranimo iz pomnilnika s tem, da ji priredimo vrednost null. S tem prirejanjem naredimo tabelo nedostopno za uporabo, iz pomnilnik pa jo (ob priliki) odstrani mehanizem za odstranjevanje ( hm., smeti) oz. garbage collector .
Vprašanje 1 | |||||||
Katera izmed kombinacij znakov (simbolov) je tista, ki vam da vedeti, da gre za tabelo ? | |||||||
[[ | |||||||
{} | |||||||
(( | |||||||
[] | |||||||
(( | |||||||
Vprašanje 2 | |||||||
Dano zaporedje stavkov | |||||||
for (int i=0;i<tab.length-1;i++){ tab[i][0]=1; tab[i][2]=tab[0][i]+1; } izvedemo na tabeli int tab[][] = new int[3][5]; Po izvedbi je v tabeli vsebina : |
|||||||
10200 10100 00000 | |||||||
10100 00000 20100 | |||||||
10200 10200 00000 | |||||||
11000 00000 22000 | |||||||
Vprašanje 3 | |||||||
Koliko celoštevilskih elementov 'vsebuje' tabela: | |||||||
int tab[][] = new int[2][3]; | |||||||
5 | |||||||
6 | |||||||
7 | |||||||
12 | |||||||
Vprašanje 4 | |||||||
Katera izmed deklaracij nakazuje, da gre za večrazsežno tabelo ? | |||||||
int [][][][]tab; | |||||||
String []tabela; | |||||||
char tab[][]; | |||||||
float [[]]tab; | |||||||
Vprašanje 5 | |||||||
Izberite stavke, ki vsebujejo pravilno deklaracijo, rezervacijo in inicializacijo večrazsežne tabele. | |||||||
int tab[][]=new int[3]; | |||||||
int tab[][]={{1,2},{3,4}}; | |||||||
int[] tab; tab=new int[3][5]; | |||||||
int [][][]tab=new int[2][2][2]; | |||||||
Vprašanje 6 | |||||||
Izberite stavek, ki padaja pravilno deklaracijo tabele, s pravilno rezervacijo in inicializacijo le te | |||||||
int tab[]=new int[2][4]; | |||||||
int tab[][]=new int[][]; | |||||||
int tab[][]=new char[1][1]; | |||||||
int tab[][]=new int[2][8]; | |||||||
Vprašanje 7 | |||||||
Dana je tabela 'tab' : | |||||||
int tab[][] = new int[2][3]; katera izmed spodnjih slik predstavlja 'vizualizacijo' take tabele ? |
|||||||
-maxInt -maxInt -maxInt -maxInt -maxInt -maxInt | |||||||
-1 -1 -1 -1 -1 -1 | |||||||
0 0 0 0 0 0 | |||||||
1 1 1 1 1 1 | |||||||
vrednosti vseh elementov tabele so neopredeljivi (naključne vrednosti) | |||||||
Vprašanje 8 | |||||||
Povežite deklaracije s smiselno ustreznimi naslavljanji elementov tabele | |||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
Vprašanje 9 | |||||||
Določite pomen posameznih deklaracij | |||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
|
|||||||
Vprašanje 10 | |||||||
Kateri izmed stavkov vrednost vseh štirih 'ogliščnih' elementov tabele | |||||||
int tab[][] = new int[2][3]; postavi na 33 ? |
|||||||
tab[0][0]=tab[2][3]=tab[0][3]=tab[2][0]=33; | |||||||
tab[1][1]=tab[2][3]=tab[1][3]=tab[2][1]=33; | |||||||
tab[0][0]=tab[1][2]=tab[0][2]=tab[1][0]=33; | |||||||
tab[0][0]=tab[0][2]=tab[3][0]=tab[2][3]=33; | |||||||
tab[0][0]=tab[2][0]=tab[1][0]=tab[1][2]=33; | |||||||
Vprašanje 11 | |||||||
Prepisati bi želeli vrednosti elementov zadnje vrstice tabele | |||||||
int [][]tab=new int[5][5]; tako, da bi bile vrednosti elementov zadnje in predzadnje vrstice po postopku enake. Izberite vse stavke,ki zadostijo podani zahtevi. |
|||||||
tab[4]=tab[5]; | |||||||
tab[3]=tab[4]; | |||||||
for(int i=0;i<5;tab[4][i]=tab[5][i],i++); | |||||||
for( int i=0;i<tab[0].length; tab[ tab[3].length-2 ][i] = tab[tab[4].length-1][i],i++); | |||||||
noben izmed zgornjih stavkov ne zadosti zahtevam | |||||||
Vprašanje 12 | |||||||
Določite pravilen rezultat izvajanja spodnjega zaporedja stavkov | |||||||
int [][]tab={{1,2,3,4},{2,2,2,2},{1,3,2,5}};
System.out.println(tab.length+tab[0].length+tab[1].length); |
|||||||
1244 | |||||||
20 | |||||||
18 | |||||||
11 | |||||||
10 | |||||||
344 | |||||||
Vprašanje 13 | |||||||
Vsebina tabele 'tab' po izvedbi | |||||||
int tab[][]=new int[3][5]; for (int i=0;i<tab.length;i++){ tab[0][i]=1; tab[2][i]=1; } je enaka : |
|||||||
11111 00000 11111 | |||||||
11100 00000 11100 | |||||||
10001 10001 10001 | |||||||
10100 10100 10100 | |||||||
pri izvajanju pride do prekoračitve obsega indeksov na tabeli,zato nobena ob zgoraj naštetih rešitev ni pravilna |
Naloga 1
Spodnji program deklarira tabelo, rezervira prostor zanjo v pomnilniku in izvrši inicializacijo:
class Nal12_1{ public static void main(String[] arg){ char tab[][]={{‘s’,’o’,’s’,’e’,’d’}, {‘o’,’p’,’e’,’r’,’a’}, {‘k’,’r’,’a’,’v’,’a’}}; v = tab.length; s = tab[0].length; System.out.println(v); System.out.println(s); System.out.println("Tabela :"+v+" x "+s); } }
Odpravite napake v programu. Kako interpretirate rezultate, ki jih nato program izpiše ? Narišite tabelo tab!
Naloga 2
Glede na program Nal12_1 izvedite naslednje :
static void izpisiVrstico(char tab[][], int vrstica);
static void izpisiVrstico(char tab[][], int stolpec);
static void izpisiTabelo(char [][]tab);
Naloga 3
Recimo, da deklaracijo tabele tab iz naloge Nal12_1 popravimo na naslednji način :
class Nal12_3{ public static void main(String[] arg){ char tab[][] = new char[3][5]; . . . . . . } }
dokončajte začeti program. Pri tem pa mora tabela vsebinsko postati enaka tisti, ki je podana v prvi nalogi. Izvedite tudi test izpisa celotne tabele na zaslon s pomočjo ustrezne metode iz druge naloge.
Naloga 4
Ponovite izvedbo naloge 3. Deklaracija tabele je v tem primeru dana z :
class Nal12_4{ public static void main(String[] arg){ char tab[][]; . . . . . .
dokončajte začeti program. Rezervacijo za vsako izmed razsežnosti bi pri tem želeli izvesti ločeno. Pri tem pa mora tabela vsebinsko postati enaka tisti, ki je podana v prvi nalogi. Izvedite tudi test izpisa celotne tabele na zaslon s pomočjo ustrezne metode iz druge naloge.
Naloga 5
Javanski program Nal12_5 prepiše vsebino elementov tabele tab1 v elemente tabele tab2 tako, da se prepiše vrednost istoležnih indeksov tabele :
class Nal12_5{ public static void main(String[] arg){ char tab1[][]={{‘s’,’o’,’s’,’e’,’d’},{‘o’,’p’,’e’,’r’,’a’}, {‘k’,’r’,’a’,’v’,’a’}}; char tab2[][]=new char[3][5]; . . .
char tab3[][] = new char[5][3];
Pri tem pa upoštevajte, da se lahko izvede prepis le takrat, kadar naslovljeni element v tabeli obstaja!
static void prepisiTabeloVDrugo(char [][]ponorna, char[][] izvorna);