Professional Documents
Culture Documents
Ai SP
Ai SP
STRUKTURE PODATAKA
Polje . . . (array u C++-u). Mehanizam udruživanja manjih dijelova strukture u veće. Polje čini
više ćelija istog tipa pohranjenih na uzastopnim adresama. Broj ćelija je unaprijed zadan i
nepromjenljiv.
Jedna ćelija se zove element polja i jednoznačno je određena pripadnom vrijednošću indeksa.
Po ugledu na C++, uzimamo da su indeksi 0, 1, 2, ... , N-1, gdje je N cjelobrojna konstanta.
Pointer . . . služi za uspostavljanje veze izmedu dijelova strukture. Pointer ili pokazivač je
ćelija koja pokazuje neku drugu ćeliju. Sadržaj pointera je adresa ćelije koju treba pokazati.
Kursor . . . također služi za uspostavljanje veze izmedu dijelova strukture. Kursor je ćelija
tipa int koja pokazuje na element nekog polja. Sadržaj kursora je indeks elementa kojeg
treba pokazati.
Dijagram ispod pokazuje primjer strukture podataka koja se sastoji od niza zapisa povezanih
pomoću pointera, te od jednog polja zapisa. Zapisi su još međusobno povezani kursorima.
3.2.1. Polja
U programiranju se često susrećemo s upotrebom jednodimenzionalnih polja odnosno
nizova. Korištenjem polja možemo na smislen način grupisati više podataka istoga tipa. Npr.,
želimo li izračunati ali i pohraniti ocjene sa ispita iz nekog predmeta za sve studente koji su
izašli na ispit, jedan od načina je korištenjem polja.
Polje, dakle, predstavlja sljedni niz memorijskih lokacija rezervisan za određeni tip podatka.
Svakom elementu polja možemo pristupiti na temelju indeksnih varijabli. Operacije pristupa
elementima polja zahtjeva O(1) vrijeme.
U ovom dijelu obradit će se osnovni pojmovi iz nizova i stringova u programskom jeziku C++.
To su:
• Deklaracija, inicijalizacija i korištenje jednodimenzionalnih i višedimenzionalnih
nizova.
• Nizovi i funkcije
• Pokazivači i nizovi
• Nizovi karaktera u C-u (C-stringovi)
• Pokazivači na nizove karaktera
• Funkcije za rad sa C-stringovima
Inicijalizacija niza
Inicijalizacija niza je dodjeljivanje vrijednosti elementima niza u istom iskazu u kome se vrši
deklaracija niza.
Inicijalizacija niza se može izvršiti ili član po član, ili je moguće koristiti sljedeći izraz:
int Ocjene[5] = {10, 6,8,7,8};
pri čemu broj vrijednosti unutar vitičastih zagrada { } ne smije biti veći od maksimalnog broja
elemenata niza koji smo naveli u okviru uglastih zagrada [ ]. Može biti manji.
Također je moguće u toku deklaracije izostaviti maksimalnu dimenziju, a samo u okviru
vitičastih zagrada inicijalizovati članove niza, što će automatski setovati maksimalnu veličinu
niza na broj unesenih elemenata. Stoga, ukoliko napišemo:
int Ocjene[] = {10, 6,8,7,8};
kreiraće se potpuno identičan niz kao u prethodnom primjeru, gdje je niz imao 5 elemenata.
U nastavku je dat primjer dodjele vrijednosti odgovarajućem članu niza, kojem naravno
pristupamo preko indeksa:
Ocjene [4] = 8;
Prethodni izraz dodjeljuje petom članu niza vrijednost 8. Kao i u Java-i, indeks niza počinje
sa nulom (Ocjene [0]) dok posljednji član niza ima indeks N-1, gde je sa N označena dimenzija
niza. Na narednoj slici je grafički prikazan niz iz prethodnog primjera:
Obzirom da svi elementi niza imaju istu veličinu (pošto se radi o istom tipu podatka),
dijeljenjem ukupne količine memorije niza sa veličinom memorije koja odgovara jednom
elementu niza dobijamo broj elemenata. Pri tome treba koristiti element sa indeksom 0 s
obzirom da niz koji je deklarisan mora imati bar jedan element.
Problem sa prethodnim kodom je taj što je uslovni izraz u okviru for naredbe netačan.
Deklarisani niz ima 5 elemenata, tako da indeksi idu u opsegu od 0 do 4. Međutim, petlja ide
od 0 do 5. Kao posljedica, u posljednjem ciklusu for petlje izvršit će se sljedeća sekvenca kôda:
if (niz[5] > maxValue)
maxValue = niz[5];
ali član niz [5] našeg niza nije definisan! Ovo može da izazove raličite probleme, a
najvjerovatnije je da će niz [5] imati neku nedodijeljenu vrijednost ili beskonačno veliki broj.
Kao posljedica greške u pisanju kôda promjenljivoj maxValue će biti dodijeljena pogrešna
vrijednost.
Ono što je još veći problem kod izlaska iz opsega je dodjela vrijednosti članu niz[5], što može
dovesti do izmjene neke druge promjenljive (ili dijela promjenljive). Ovakve greške u
programu su jedne od težih za otkrivanje a mogu da izazovu ozbiljne probleme!
Prosljeđivanje niza funkciji
Da bi se niz proslijedio funkciji kroz listu argumenata, postoje tri načina na koja se to može
uraditi. Sva tri načina su veoma slična međusobno, i proizvode isti rezultat, zato što svi
slučajevi šalju poruku kompajleru da se radi sa pokazivačem na cjelobrojnu vrijednost. Na
sličan način je moguće proslijediti i višedimenzionalne nizove što će biti pokazano u
nastavku. Postoje tri načina da se niz kroz listu argumenata proslijedi funkciji: kao pokazivač,
kao dimenzionisani niz i kao nedimenzionisani niz.
• Prosljeđivanje niza korištenjem pokazivača kao formalnog parametra:
void myFunction(int *param)
{
...
}
• Formalni parametar kao dimenzionisani niz, kao što je dato u nastavku:
void myFunction(int param[10])
{
...
}
• Formalni parametar kao nedimenzionisani niz:
void myFunction(int param[])
{
...
}
Kao što se vidi iz prethodnog primjera, nije neophodno navesti dimenziju niza u listi
formalnih parametara jer C/C++ ne provjerava granice formalnih parametara (isto je kod C#
i Java).
Problem pretraživanja
Polje kao skup podataka istog tipa može biti efikasna struktura podataka za sortiranje ili
pretraživanje brojeva.
Npr., neka imamo:
Ulaz: Niz od n brojeva A = {a1, a2, . . . , an} i vrijednost x
Izlaz: Indeks i takav da x = A[i] ili specijalna vrijednost NIL ukoliko x nije u A.
U pseudo jeziku predstavit ćemo algoritam koji dati broj x nalazi u zadanom polju u O(n)
vremenu. Definirat ćemo funkciju koja će nam vratiti indeks lokacije u kojoj je nađeno x.
Ukoliko x nije u polju vratit će se prazan indeks. Koristit ćemo algoritam sekvencijalnog
pretraživanja.
seqPretrazi(A, x)
1 for i 1 to length(n)
2 do if x = A[i]
3 then return i
4 return NIL
Uočavamo da vrijeme izvršenja algoritma zavisi od broja iteracija for petlje što nam daje O(n)
vremensku složenost. Korektnost algoritma je jasna: prolazimo kroz sve elemente polja,
ukoliko takav broj nađemo, vraćamo indeks tog mjesta. Ako ne nađemo, sa return NIL
vraćamo prazan indeks. U pseudokodu je indeks prvog elementa označen brojem 1.
Konkretan programski kôd za slučaj pronalaska zajedničkih elemenata u dva 1D polja uz
pomoć algoritma sekvencijalnog pretraživanja izgleda:
#include <iostream>
#include <string>
using namespace std;
int seqPretrazivanje(const int x[], int size, int key)
{
for (int i = 0; i < size; i++)
if (key == x[i]) return i;
return -1;
}
void presjek(const int set1[], int size1,
const int set2[], int size2, int s[], int &size)
{
size = 0;
for (int i = 0; i < size1; i++)
if (seqPretrazivanje(set2, size2, set1[i]) > -1)
s[size++] = set1[i];
}
void display(const int x[], int size)
{
for (int i = 0; i < size; i++)
cout << x[i] << endl;
}
void main()
{
int x[] = { 1,2,3,4 };
int y[] = { 10,2,30,4,50 };
int size = 5;
int p[5];
presjek(x, 4, y, 5, p, size);
cout << "Zajednicki elementi su:" << endl;
display(p, size);
}
Izlaz:
4/10/2018
Sadržaj predmeta:
• Uvod u algoritme, analize algoritama
ALGORITMI I STRUKTURE PODATAKA • Složenost i ocjena složenosti algoritama, notacije
• Definicija i implementacija i aplikacija složenih struktura
podatka kao što su:
• Nizovi: jednodimenzionalni i višedimenzionalni nizovi
• Liste: jednostruko povezane, dvostruko povezane,
ć prstenovi i specijalni slučajevi kao što su stekovi i
redovi.
• Stabla: binarna, uravnotežena, stabla za traženje.
• Heap, hash tabele, grafovi.
1 2
Mehanizam udruživanja manjih dijelova Zapis čini više ćelija, koje ne moraju biti istog tipa, ali
strukture u veće. su pohranjene na uzastopnim adresama.
Polje čini više ćelija istog tipa pohranjenih na Broj, redosljed i tip ćelija je unaprijed zadan i
uzastopnim adresama. nepromjenljiv.
Broj ćelija je unaprijed zadan i nepromjenljiv. Pojedina ćelija se zove komponenta zapisa.
Jedna ćelija se zove element polja i Polja i zapisi se mogu kombinirati. (Npr, možemo imati
jednoznačno je određena pripadnom vrijednošću polje zapisa, zapis čije pojedine komponente su polja, polje
indeksa.
od polja, zapis čija komponenta je zapis, i slično.)
Elementi od kojih se grade strukture podataka Elementi od kojih se grade strukture podataka
Pointer . . . služi za uspostavljanje veze izmedu Struktura - manje cjeline se udružuju u veće i
dijelova strukture. međusobno povezuju vezama.
Pointer ili pokazivač je ćelija koja pokazuje neku Dijagram pokazuje primjer strukture podataka koja se
drugu ćeliju. sastoji od niza zapisa povezanih pomoću pointera, te od
Sadržaj pointera je adresa ćelije koju treba jednog polja zapisa. Zapisi su još međusobno povezani
pokazati. kursorima.
Kursor . . . također služi za uspostavljanje veze
izmedu dijelova strukture.
Kursor je ćelija tipa int koja pokazuje na element
nekog polja.
Sadržaj kursora je indeks elementa kojeg treba
pokazati.
1
4/10/2018
Povezane liste
Stekovi
Redovi
}
V1 Ako je Vi=x onda
V2 Ispiši “DA, na “,i,”. mjestu”
Završi algoritam
Vi Niz V ima N elemenata Ispiši “NE”
VN
Vremenska složenost algoritma: O(N) - “linearna složenost”
i=1
Dok god je Vi<=x činiti
Ako je Vi=x onda
dg=1 s=(dg+gg)/2 gg=N
Ispiši “DA, na “,i,”. mjestu”
Završi algoritam
i++
Ispiši “NE” - ako su podaci poredani (sortirani) onda
ne moramo provjeravati sve podatke!
Vremenska složenost algoritma: O(N) - “linearna složenost”
2
4/10/2018
Česta greška:
Jednodimenzionalno polje - niz
• Koristimo jednodimenzionalne (1D) nizove da na
Out-of-bound Run-time Error
jednostavan način sačuvamo i pristupimo spisku • Svi C ++ jednodimenzionalni nizovi sa N
vrijednosti podataka tako što ćemo ovim
vrijednostima dati zajedničko ime, npr
elemenata počinju sa indeksom 0 i završavaju
int x[4]; // sve vrijednosti su nazvane x se indeksom N-1.
10 x[0] const int N=5;
x[0] = 10; // vrijednost 1.člana je 10
x[1] = 5; // vrijednost 2. člana je 5 5 x[1] int v[N]; // sadrži 5 elemenata
x[2] = 20; // vrijednost 3. člana je 20 • Česta je greška u pokušaju pristupa N-tom
20 x[2]
x[3] = 30; // vrijednost 4. člana je 30
30 x[3]
elementu, npr. v [5] ili V [N], pošto je indeks
posljednjeg unosa niza N-1, a ne N.
3
4/10/2018
• Tačno:
int x[10];
// Prikazivanje jedne po jedne vrijednosti :
for (int index=0; index<10; index++)
cout << x[index] << endl;
4
4/10/2018
5
4/10/2018
int range (const int x[ ], int n) void multiply( int x[ ], int n, const int value)
{ {
return max (x, n) – min (x, n); for (int i=0; i<n; i++) x[i] *= value;
} }
6
4/10/2018
void add (const int x[], const int y[], int z[], int n)
int dotProduct( int x[ ], int y[ ], int n) {
{ for (int i=0; i<n; i++) z[i] = x[i] + y[i];
int sum = 0; }
for (int i=0; i<n; i++)
sum += x[i] * y[i]; void subtract (const int x[], const int y[], int z[], int n)
{
return sum;
for (int i=0; i<n; i++) z[i] = x[i] - y[i];
}
}
Primjer : Unija elemenata dva niza Primjer primjene polja: Konverzija cijelog broja iz dekadnog u
binarni b.s.
void unija (const int set1[], int size1, const int set2[], int size2,
int s[], int &size)
{
size = size1;
for(int i=0; i<size; i++) s[i]=set1[i];
for(int i=0; i<size2; i++)
if (seqSearch(s, size, set2[i]) == -1)
s[size++] = set2[i];
}
7
4/10/2018
8
4/10/2018
Sadržaj predmeta:
• Uvod u algoritme, analize algoritama
ALGORITMI I STRUKTURE PODATAKA • Složenost i ocjena složenosti algoritama, notacije
• Definicija i implementacija i aplikacija složenih struktura
podatka kao što su:
• Nizovi: jednodimenzionalni i višedimenzionalni nizovi
• Liste: jednostruko povezane, dvostruko povezane,
ć prstenovi i specijalni slučajevi kao što su stekovi i
redovi.
• Stabla: binarna, uravnotežena, stabla za traženje.
• Heap, hash tabele, grafovi.
1 2
1
4/10/2018
2
4/10/2018
2D polja
Svaki element polja je određen brojem reda i kolone
u kojima se nalazi.
3
4/10/2018
4
4/10/2018
5
4/10/2018
6
AiSP (P) Primjeri sa nizovima _ AISP predavanje 3 i 4
Rez:
#include <iostream>
#include <string>
using namespace std;
Rez:
3
for (int i = 0; i < size; i++)
if (key == x[i]) return i;
return -1;
}
void razlika(const int set1[], int size1,
const int set2[], int size2, int s[], int &size)
{
size = 0;
for (int i = 0; i < size1; i++)
if (seqPretrazivanje(set2, size2, set1[i]) == -1)
s[size++] = set1[i];
}
Rez:
5
n /= 2;
bits++;
}
for (index = bits - 1; index >= 0; index--)
cout << binary[index];
cout << endl;
}
}
Rez:
7
insertionSort(array, 10);
display("Sortirano polje: ", array, 10);
}
8
PRIMJERI SA 5.PREDAVANJA IZ AiSP (MATRICE)
1.
#include<iostream>
using namespace std;
int main()
{
const int rows = 4;
const int cols = 3;
int mat[rows][cols];
int i, j;
//inicijalizacija
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
mat[i][j] = 0;
//ispis
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
cout << mat[i][j] << "\t";
cout << endl;
}
//unos elemenata
for (i = 0; i < rows; i++)
for (j = 0; j < cols; j++)
cin >> mat[i][j];
//ispis
for (i = 0; i < rows; i++)
{
for (j = 0; j < cols; j++)
cout << mat[i][j] << "\t";
cout << endl;
}
//suma svakog reda
for (i = 0; i < rows; i++)
{
int sum = 0;
for (j = 0; j < cols; j++)
sum += mat[i][j];
cout << "Suma " << i + 1 << ". reda je " << sum << endl;
}
//suma svake kolone
for (j = 0; j < cols; j++)
{
int sum = 0;
for (i = 0; i < rows; i++)
sum += mat[i][j];
cout << "Suma " << j + 1 << ". kolone je " << sum << endl;
}
1
//najveći element reda
for (i = 0; i < rows; i++)
{
int max = mat[i][0];
for (j = 0; j < cols; j++)
if (mat[i][j] > max)
max = mat[i][j];
cout << "Najveci el u " << i + 1 << ". redu je " << max << endl;
}
//najveći element kolone
for (j = 0; j < cols; j++)
{
int max = mat[0][j];
for (i = 0; i < rows; i++)
if (mat[i][j] > max)
max = mat[i][j];
cout << "Najveci el u " << j + 1 << ". koloni je " << max << endl;
}
}
Gornji primjer sa fjama
#include<iostream>
using namespace std;
const int rows = 4;
const int cols = 3;
void InitMat(int mat[][cols], int rows, int cols)
{
//inicijalizacija
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
mat[i][j] = 0;
}
//ispis
void IspisMat(int mat[][cols], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
for (int j = 0; j < cols; j++)
cout << mat[i][j] << "\t";
cout << endl;
}
}
//unos elemenata
void UnosMat(int mat[][cols], int rows, int cols)
{
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
cin >> mat[i][j];
}
//suma svakog reda
void SumaRedaMat(int mat[][cols], int rows, int cols)
{
2
for (int i = 0; i < rows; i++)
{
int sum = 0;
for (int j = 0; j < cols; j++)
sum += mat[i][j];
cout << "Suma " << i + 1 << ". reda je " << sum << endl;
}
}
//suma svake kolone
void SumaKolMat(int mat[][cols], int rows, int cols)
{
for (int j = 0; j < cols; j++)
{
int sum = 0;
for (int i = 0; i < rows; i++)
sum += mat[i][j];
cout << "Suma " << j + 1 << ". kolone je " << sum << endl;
}
}
//najveći element reda
void MaxElRedMat(int mat[][cols], int rows, int cols)
{
for (int i = 0; i < rows; i++)
{
int max = mat[i][0];
for (int j = 0; j < cols; j++)
if (mat[i][j] > max)
max = mat[i][j];
cout << "Najveci el u " << i + 1 << ". redu je " << max << endl;
}
}
//najveći element kolone
void MaxElKolMat(int mat[][cols], int rows, int cols)
{
for (int j = 0; j < cols; j++)
{
int max = mat[0][j];
for (int i = 0; i < rows; i++)
if (mat[i][j] > max)
max = mat[i][j];
cout << "Najveci el u " << j + 1 << ". koloni je " << max << endl;
}
}
int main()
{
int mat[rows][cols];
int i, j;
//inicijalizacija
InitMat(mat, rows, cols);
//ispis
IspisMat(mat, rows, cols);
//unos elemenata
UnosMat(mat, rows, cols);
//ispis
3
IspisMat(mat, rows, cols);
//suma svakog reda
SumaRedaMat(mat, rows, cols);
//suma svake kolone
SumaKolMat(mat, rows, cols);
//najveći element reda
MaxElRedMat(mat, rows, cols);
//najveći element kolone
MaxElKolMat(mat, rows, cols);
}
2.
Primjer: Napisati funkciju pod nazivom donja_polovica () koja uzima dvodimenzionalni niz A, sa 5
redova i 5 kolona kao argumentom i prikazuje donju polovicu polja.
#include <iostream>
using namespace std;
int main()
{
int _2DArray[5][5] = {
{ 1, 2, 3,4,5 },
{ 6,7, 8, 9,10 },
{ 1, 1, 1,1,1 },
{ 2, 2, 2,2,2 },
{ 6,7,8,9,3 },
};
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
if (j > i)_2DArray[i][j] = 0;
}
cout << endl;
}
for (int i = 0; i < 5; i++)
{
for (int j = 0; j < 5; j++)
{
cout << _2DArray[i][j] << " ";
}
cout << endl;
}
cout << endl;
return 0;
}
3.
Primjer: Napisati funkciju koja uzima 2D niz integer-a i njegovu veličinu kao argumente i prikazuje elemente
koji leže na dijagonalama.
#include <iostream>
using namespace std;
const int n = 5;
void Dijagonale(int A[n][n], int size)
{
4
int i;
cout << "Glavna dijagonala : " << endl;
for (i = 0; i < n; i++)
cout << A[i][i] << " ";
cout << endl;
cout << "Sporedna dijagonala : " << endl;
for (i = 0; i < n; i++)
cout << A[i][n - (i + 1)] << " ";
cout << endl;
}
int main()
{
int _2DArray[5][5] = {
{ 1, 2, 3,4,5 },
{ 6,7, 8, 9,10 },
{ 1, 1, 1,1,1 },
{ 2, 2, 2,2,2 },
{ 6,7,8,9,3 },
};
Dijagonale(_2DArray, n);
return 0;
}
4.
Kreiranje matrice preko 1D niza pokazivača na 1D nizove
#include <iostream>
using namespace std;
const int n = 5;
int main()
{
int a1[3] = { 1,2,3 };
int a2[3] = { 4,5,6 };
int a3[3] = { 7,8,9 };
int* p1, *p2, *p3;
p1 = a1; p2 = a2; p3 = a3;
int* p[3] = { p1,p2,p3 };
for (int i = 0; i < 3; i++)
{
for (int j = 0; j < 3; j++)
cout << *(p[i] + j)<<"\t";
cout << endl;
}
return 0;
}
5
STRING
#include <iostream>
using namespace std;
const int n = 5;
int main()
{
char rijec[4] = { 'D', 'A', 'N','\0' }; //C stil znakovnog niza(stringa)
cout << "Preko imena niza: " << rijec << endl;
char * p1 = rijec;
cout << "Preko pokazivaca: " << p1 << endl;
cout << "Preko pokazivacke aritmetike: ";
for (int i = 0; i < 3; i++)
cout << *(p1 + i);
cout << endl;
char *p2 = "Microsoft";
cout << "Preko pokazivaca p2: " << p2 << endl;
return 0;
}