Strukture Strukture Strukturirani (složeni) tip podataka koji definiše korisnik sastoji se od više komponenti komponente imaju identifikatore ne moraju biti istog tipa struktura se smatra jednim objektom (može biti i vrednost funkcije) Razlike u odnosu na niz kod niza istorodne komponente -zasebni objekti, identifikuju se indeksima vrednost funkcije ne može da bude niz (može pokazivač) Koristi se za složene objekte logički povezane informacije Strukture Strukture Definicija naredbom struct + ime + opis struct tacka {int x, y; a, b, c; struct pravougaonik {struct tacka dole_levo, gore_desno;; struct krug {double r; struct tacka centar;; komponente vidljive samo unutar strukure kojoj pripadaju mogu ista imena u različitim strukturama mogu ista imena kao promenljive 1
Strukture Strukture definisanje promenljivih ovog tipa moguće pozvati se na ranije definisanu strukturu (za poziv na tip mora: struct + identifikator strukture - kao kod enum) dati njen opis direktno (može se izostaviti identifikator strukture) dodela početnih vrednosti niz vrednosti unutar zagrada (kao kod niza) konstantni izrazi dodeljuju se sukcesivnim komponenatama strukture broj i tipovi vrednosti moraju da se slažu sa komponentama, više vrednosti nije dozvoljeno ako je manje vrednosti, preostale komponente se inicijalizuju nulama Strukture Strukture dodela početnih vrednosti u obliku izraza koji predstavlja poziv funkcije koja je tipa te strukture struct tacka p = {35, -12, q; struct pravougaonik w, x, y = {{1, 1, {3, 3; mogu se definisati i nizovi struktura ako se sa typedef definiše strukturni tip, njegov identifikator se može koristiti kao oznaka tipa i bez službene reči struct 2
Strukture typedef struct {char ime[16], prezime[16]; ime; typedef struct { char dan, mesec; short int godina; datum; typedef struct { char maticni_broj[13]; ime osoba; datum datum_rodjenja; char adresa[30]; gradjanin; dozvoljena dodela vrednosti (=) za promenljive istog strukturnog tipa prepišu se sve komponente gradjanin g1, g2, g3; dve strukturne promenjive su istog tipa ako: su definisane istom naredbom za njihovu definiciju se koristi isti identifikator tipa Primer: a i b različitog tipa imaju isti opis struct {int x,y; a; struct {int x,y; b; 3
moguća primena adresnog operatora, kao i pokazivači na strukture struct krug *p; struktura može biti i argument funkcije (po vrednosti) kao i vrednost funkcije kako niz ne može biti vrednost funkcije, može struktura sa nizom kao jednom komponentom od struktura mogu da se prave nizovi veličina strukture se dobija sa sizeof (ne mora da bude zbir komponenti ako postoje neka ograničenja u smeštanju) za pristup komponentama se koristi binarni operator tačka (.) a.x (*p).r (zagrade su neophodne!!!) zbog čiste upotrebe pokazivača na strukture - binarni operator -> a.x=13; a.z=-22; a={13,-22 (samo inicijalizacija!!!) x.dole_levo.x=4; x.dole_levo.y=-5; x.gore_desno.x=7; x.gore_desno.y=0; w.dole_levo=a; w.gore_desno=p; p->r 4
/* definisanje tipa Tacka */ struct tacka {int x,y;; typedef struct tacka Tacka; /* formiranje tačke od zadatih komponenti*/ Tacka pravi_tacku (int x, int y) { Tacka t; t.x=x; t.y=y; return t;... /* izračunavanje rastojanja između tačaka */ #include <math.h> double rastojanje (Tacka g, Tacka h) { return sqrt(pow(g.x-h.x,2)+pow(g.y-h.y,2)); const Tacka NULA = {0,0;... Dinamičke strukture podataka /* nalaženje tačke najbliže koordinatnom početku */ Tacka * najbliza(tacka a[], int n) { Tacka *min = a; double r = rastojanje(a[0],nula), s; for (int i=1; i<n; i++) { s = rastojanje(a[i],nula); if (s<r) {r=s; min=a+i; return min; strukture pogodne za formiranje složenih dinamičkih struktura podataka (promenljiva i veličina i logička povezanost) obično se sastoje od korisnog sadržaja i pokazivača na druge objekte 5
Dinamičke strukture podataka Dinamičke strukture podataka Primer linearne liste za predstavljanje nizova objekata dinamičko stvaranje, brisanje, preuređivanje objekata u listi typedef struct element { int broj; struct element *sled ; Element; sled -pokazivač na naredni član liste definicija moguća jer je u trenutku deklaracije pokazivača, identifikator strukture je već definisan nemoguća "rekurzivna" definicija kada je komponenta strukture sama ta struktura Dinamičke strukture podataka Dinamičke strukture podataka Linearna lista typedef struct element { int broj; struct element *sled ; Element; Element *niz; sled -pokazivač na naredni član liste niz pokazivač na početak liste dodavanje, brisanje i uređivanje elemenata iskazuje podešavanje pokazivača nedostaci: dodatni prostor za pokazivače samo sekvencijalan ali ne i direktan pristup 6
Dinamičke strukture podataka Dinamičke strukture podataka Druga primena -binarno stablo koren i dva podstabla može da se definiše rekurzivno jer je bilo koji podskup povezanih čvorova -stablo struct Cvor { int broj; struct Cvor *levi, *desni; *stablo; stablo -pokazivač na koreni čvor bolje definisati sa typedef kao u primeru sa listom Unije Unije strukturirani tipovi koji omogućavaju da se u isti memorijski prostor smeštaju podaci različitih tipova u različitim vremenskim intervalima naredba union (sintaksa kao za struct) struct { union { int i; int i; double d; double d; char *c; char *c; s; u; 7
Unije Unije s: s.i s.d s.c u: u.i u.d u.c za razliku od strukture, u jednom momentu samo jedna komponenta ima definisanu vrednost sizeof s а) б) sizeof u veličina određena najvećom komponentom Unije Polja bitova programer treba da vodi računa o konzistentnom korišćenju komponenti (posledice su nepredvidive ako se upiše u jednu, a koristi druga komponenta) struktura čije su komponente dužine nekoliko bitova (pakuju se na mašinski zavisan način) često za opisivanje hardverskih registara programi koji koriste polja bitova su obično mašinski zavisni 8
Polja bitova Polja bitova Standard ne definiše: deklaracija da li polje bitova može da bude duže od mašinske reči kao za strukturne tipove da li komponenta može da bude duža od mašinske reči da li komponenta može da prelazi granicu reči da li se ređaju zdesna ili obrnuto sve komponente moraju da budu unsigned int dužina polja se navodi u bitovima Polja bitova Jednostruko ulančane liste struct { unsigned int n:1, z:1, prio:4; status_reg; status_reg.prio=5; if (status_reg.n!= 1 && status_reg.z!= 0)... lst: 5 3 2 6 5 3 NULL typedef struct elem { int broj; struct elem *sled; Elem; 9
Obilazak liste određivanje broja elemenata Obilazak liste ispisivanje svih elemenata intduz (Elem *lst) { Elem *tek; int n = 0; for (tek=lst; tek; tek=tek->sled) n++; return n; void pisi (Elem *lst) { Elem *tek; for (tek=lst; tek; tek=tek->sled) printf ("%d ", tek->broj); printf ("\n"); Dodavanje novog elementa na početak liste Dodavanje novog elementa na kraj liste Elem *na_pocetak (Elem *lst, int b) { Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = lst; lst = novi; return lst; Elem *na_kraj (Elem *lst, int b) { Elem *tek, *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = NULL; if (!lst) lst = novi; else { for (tek=lst; tek->sled; tek=tek->sled); tek->sled = novi; return lst; 10
Umetanje elementa u rastuće uređenu listu Sortiranje liste metodom izbora Elem *umetni (Elem *lst, int b) { Elem *tek = lst, *pret = NULL, *novi; while (tek && tek->broj < b) { pret = tek; tek = tek->sled; novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = tek; if (!pret) lst = novi; else pret->sled = novi; return lst; void uredi (Elem *lst) { Elem *i, *j; int p; for (i=lst; i; i=i->sled) for (j=i->sled; j; j=j->sled) if (j->broj < i->broj) { p = i->broj; i->broj = j->broj; j->broj = p; Brisanje svih elemenata liste Izostavljanje elemenata sa datom vrednošću (1) void brisi (Elem *lst) { Elem *stari; while (lst) { stari = lst; lst = lst->sled; free (stari); Elem *izostavi (Elem *lst, int b) { Elem *tek = lst, *pret = NULL, *stari; while (tek) if (tek->broj!= b) { pret = tek; tek = tek->sled; 11
Izostavljanje elemenata sa datom vrednošću (2) Dvostruko ulančane liste else { /* ako se element izostavlja */ stari = tek; tek = tek->sled; if (!pret) lst = tek; else pret->sled = tek; free (stari); return lst; prvi: NULL 5 3 6 2 NULL typedef struct elem { int broj; struct elem *sled, *pret; Elem; typedef struct { Elem*prvi, *posl Lista; :posl Prazna lista i obilazak liste Ispisivanje liste u napred Prazna lista: oba pokazivača su NULL Lista lst = {NULL, NULL; Obilazak u napred: for (tek=lst.prvi; tek; tek=tek->sled) { Obilazak u nazad: for (tek=lst.posl; tek; tek=tek->pret) { void pisi_unapred (Lista lst) { Elem *tek; for (tek=lst.prvi; tek; tek=tek->sled) printf ("%d ", tek->broj); printf ("\n"); 12
Ispisivanje liste u nazad Nalaženje prve pojave broja void pisi_unazad (Lista lst) { Elem *tek; for (tek=lst.posl; tek; tek=tek->pret) printf ("%d ", tek->broj); printf ("\n"); Elem *nadji_prvi (Lista lst, int b) { Elem *tek; for (tek=lst.prvi; tek; tek=tek->sled) if (tek->broj == b) return tek; return NULL; Nalaženje poslednje pojave broja Dodavanje na početak Elem *nadji_posl (Lista lst, int b) { Elem *tek; for (tek=lst.posl; tek; tek=tek->pret) if (tek->broj == b) return tek; return NULL; void na_pocetak (Lista *plst, int b) { Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = plst->prvi; novi->pret = NULL; if (! plst->posl) plst->posl = novi; else plst->prvi->pret = novi; plst->prvi = novi; 13
Dodavanje na kraj Brisanje svih elemenata void na_kraj (Lista *plst, int b) { Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->pret = plst->posl; novi->sled = NULL; if (! plst->prvi) plst->prvi = novi; else plst->posl->sled = novi; plst->posl = novi; Izostavljanje prve pojave broja void brisi (Lista *plst) { Elem *tek = plst->prvi, *stari; while (tek) { stari = tek; tek = tek->sled; free (stari); plst->prvi = plst->posl = NULL; Izostavljanje poslednje pojave broja void izostavi_prvi (Lista *plst, int b) { Elem *tek = nadji_prvi (*plst, b); if (tek) { if (! tek->pret) plst->prvi = tek->sled; else tek->pret->sled = tek->sled; if (! tek->sled) plst->posl = tek->pret; else tek->sled->pret = tek->pret; free (tek); void izostavi_posl (Lista *plst, int b){ Elem *tek = nadji_posl (*plst, b); if (tek) { if (! tek->pret) plst->prvi = tek->sled; else tek->pret->sled = tek->sled; if (! tek->sled) plst->posl = tek->pret; else tek->sled->pret = tek->pret; free (tek); 14