1. 0BLINEARNE STRUKTURE PODATAKA

Like dokumenter
/* Adresu promenjive x zapamticemo u novoj promeljivoj. Nova promenljiva je tipa pokazivaca na int (int*) */ int* px;

Zadatak 1 strukture (C110) P2: Jedanaesta nedelja Strukture i liste. Strukture na jeziku C (2) Strukture na jeziku C (1)

Strukture. Strukturirani (složeni) tip podataka koji definiše korisnik. Razlike u odnosu na niz

Programiranje 1 grupno spremanje (zadaci) datoteke

Složeni tipovi podataka

Del 1 En oversikt over C-programmering

Kapittel 1 En oversikt over C-språket

ELEKTROTEHNIČKI FAKULTET UNIVERZITETA U BEOGRADU PROGRAMIRANJE 2 MATERIJALI ZA PRIPREMU ISPITA. verzija:

Del 4 Noen spesielle C-elementer

Dagens tema C, adresser og pekere

Ark 3 av 26. printf("i adresse %08x ligger b med verdien %d.\n", &b, b); printf("i adresse %08x ligger a med verdien %d.

Oving 2. Oppgave 1. #include <stdio.h> int main(int argc, char **argv) { char *navn = argv[1]; printf ("Navnet ditt er %s\n", navn); } Oppgave 2

Dagens tema INF2270. Cs preprosessor. Separat kompilering av C funksjoner. C og minnet. Dag Langmyhr,Ifi,UiO: Forelesning 5. februar 2007 Ark 1 av 15

Objektno orijentisano programiranje 2. Tipovi podataka u C#

Vektorer. Dagens tema. Deklarasjon. Bruk

Dagens tema INF1070. Vektorer (array er) Tekster (string er) Adresser og pekere. Dynamisk allokering

1 REALNE FUNKCIJE REALNE VARIJABLE

IN 147 Program og maskinvare

Dagens tema. Kort repetisjon om rutiner. Programmering i C Variable og adresser. Vektorer. Tekster. Preprosessoren. Separat kompilering

Uvod u Veb i Internet tehnologije HTML

Dagens tema. Adresser som parametre Dynamisk allokering Signaturer Definisjon av nye typenavn Typekonvertering Pekere og vektorer

Programmeringsspråket C Del 3. Hans Petter Taugbøl Kragset

Izmena i dopuna konkursne dokumentacije

Riješeni zadaci: Funkcije

Dagens tema INF1070. Info om C. Cs preprosessor. Feilsøking. Dag Langmyhr,Ifi,UiO: Forelesning 31. januar 2005 Ark 1 av 29

Informasjon om C. Dagens tema INF1070 INF1070 INF1070 INF1070. Den viktigste kilden til informasjon om C (utenom en god. C-funksjonene.

Del 2 Tabeller, arrays, strenger

Cs preprosessor. Dagens tema. Betinget kompilering

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Neprekidne funkcije nestandardni pristup

do minimalno 8 kreativnih objava mjesečno Povlaštena cijena nakon završetka akcije: 900,00 kn

Dagens tema. Rutiner i LC-2 Og her er tilsvarende kode for LC-2: Funksjoner i C Her er det samme programmet i C: Kort repetisjon om rutiner

Programmeringsspråket C Del 2. Michael Welzl

ALUMINIJSKE VODILICE ZA ODJELJIVANJE PROSTORA

Kartlegging av leseferdighet Trinn 2 og 3 på bosnisk

IN 147 Program og maskinvare

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

Dagens tema. Cs preprosessor Separat kompilering av C-funksjoner C og minnet Oversikt over operatorene

Dagens tema. C-programmering. Nøkkelen til å forstå C-programmering ligger i å forstå hvordan minnet brukes.

MINIMARK stampac za industrijsko obelezavanje

IN 147 Program og maskinvare

Oversikt. Introduksjon Kildekode Kompilering Hello world Hello world med argumenter. 1 C programmering. 2 Funksjoner. 3 Datatyper. 4 Pekere og arrays

4. Grafič ke funkčije

Dagens tema INF1070. Signaturer. Typekonvertering. Pekere og vektorer. struct-er. Definisjon av nye typenavn. Lister

1. DHB-E 18/21/24 Sli art ELEKTRONIČKI PROTOČNI GRIJAČ VODE

Dagens tema: Datastrukturer

IN 147 Program og maskinvare

Repetisjon fra sist - 1: Plan for dagen. Repetisjon fra sist 2: Hva jeg glemte sist: Nyttige Kommandoer

Programmeringsspråket C Del 3. Michael Welzl

Dagens tema INF1070. Vektorer (array-er) Tekster (string-er) Adresser og pekere. Dynamisk allokering

Ord og begreper. Norsk Morsmål: Tegning (hvis aktuelt)

SECURIT table za pisanje kredom TABLE STONE ZA PISANJE KREDOM ILI KREDA MARKEROM...

GJØVIK INGENIØRHØGSKOLE

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C Del 3

Programmeringsspråket C

Nybegynnerkurs i C. Øyvind Grønnesby. 14. oktober Introduksjon Typer Operatorer Kontrollstrukturer Pekere Makroer Lenker

Løsningsforslag til 2. del av Del - EKSAMEN

HØGSKOLEN I SØR-TRØNDELAG Avdeling for informatikk og e-læring - AITeL

Pekere og vektorer. Dagens tema. I C gjelder en litt uventet konvensjon:

Dagens tema. Det siste om C Pekere og vektorer. Pekere til pekere. Vanlige pekerfeil. struct-er og typedef. Lister. Feilsøking

Programmeringsspråket C Del 2

Programmeringsspråket C Del 2

Programmeringsspråket C Del 2

Tru64: Uvod - alati i naredbe. Dinko Korunić, InfoMAR d.o.o. v1.2, travanj 2006.

IN 147 Program og maskinvare. Dagens tema

Løsningsforslag til eksamen i IN 147 og IN 147A

Primena računara u fizičkoj hemiji. Profesor: Miloš Mojović Asistent: Aleksandar Ignjatović

E K S A M E N. Grunnleggende datakunnskap og programmering 02HIND*, 02HINE*, 02HDMU*, 02HING*, 02HGEOMAA, 02HSIV5

Signaturer. Dagens tema. En vanlig feil int-funksjon. Dette kan noen ganger gi rare feilmeldinger: INF1070 INF1070 INF1070 INF1070

IN 147 Program og maskinvare

INF1000 (Uke 5) Mer om løkker, arrayer og metoder

Del 3: Evaluere uttrykk

Administrivia INF 3110/ INF /02/2005 1

Dagens tema INF1070. Bit fikling. Makroer. Blanding av C og assemblerkode. Mer om Core War. Dag Langmyhr,Ifi,UiO: Forelesning 22. mai 2006 Ark 1 av 25

Sveučilište u Zagrebu PMF Matematički odsjek. Mreže računala. Vježbe 04. Zvonimir Bujanović Slaven Kožić Vinko Petričević

Dagens tema. Dynamisk allokering Signaturer Definisjon av typer og nye typenavn Typekonvertering Pekere, vektorer og lister Dokumentasjon

Dagens tema. Mer om C Enkle datatyper Sammensatte datatyper: Vektorer og matriser Tekster Mengder Strukturer Unioner Ringbuffere

MODIFIKACIJE METODA MATEMATIČKOG PROGRAMIRANJA I PRIMENE

Kontinuasjonseksamen

Minneområder Det er vanlig å dele opp minnet til en prosess i disse ulike områdene: Fast minne Store og små indianere «align» ing struct er

Kako dostaviti logo. USBnet. Powered by

ZADACI ZA KVALIFIKACIONI ISPIT IZ HEMIJE. 1. Napišite elektronsku konfiguraciju broma, čiji je atomski broj Z= 35.

Løsningsforslag til 2. del av Del - EKSAMEN

Dagens tema INF2270. Signaturer. Typekonvertering. Pekere og vektorer. struct er. Definisjon av nye typenavn. Lister. Info om C

E K S A M E N. Grunnleggende datakunnskap og programmering 98HINDA / 98HINDB / 98HINEA 98HDMUA / 98HDMUB / 98HINGA

INF januar 2015 Stein Michael Storleer (michael) Lenkelister

Programmeringsspråket C

Programmeringsspråket C Del 2. Hans Petter Taugbøl Kragset

EKSAMENSOPPGAVE. INF-1100 Innføring i programmering og datamaskiners virkemåte. Ingen. Elektronisk (WiseFlow) Robert Pettersen

Høgskolen i Gjøvik Institutt for informatikk og medieteknikk E K S A M E N. Grunnleggende programmering

Kontinuasjonseksamen

i=0 Repetisjon: arrayer Forelesning inf Java 4 Repetisjon: nesting av løkker Repetisjon: nesting av løkker 0*0 0*2 0*3 0*1 0*4

Forelesning inf Java 4

Høgskolen i Gjøvik Avdeling for informatikk og medieteknikk. Eksamen. Objekt-orientert programmering

UNIVERSITETET I OSLO

Transkript:

1. 0BLINEARNE STRUKTURE PODATAKA 1.1. 1BPOLJE 1.1.1. 5BDEFINICIJE I STRUKTURA Polje (array) predstavlja linearnu homogenu statičku strukturu podataka i sastoji se od fiksnog broja komponenata istog tipa. Svaki element polja se može označiti pomoću indeksa i svakom se elementu može direktno pristupati. Ukupan broj komponenti polja određen je pri njegovom opisu i ne može se menjati. Polje može biti jednodimenzionalno i višedimenzionalno. Adresa i-te komponente vektora A je data jednačinom: gde su: LR0R LR0R+c*(i-1), adresa prve reči prvog elementa vektora A, a c broj reči pridružen svakom elementu. Dvodimenzionalna polja se mogu memorisati po vrstama ili kolonama i mogu se prikazati ekvivalentnim jednodimenzionalnim vektorom. Adresa elementa A[i,j] dvodimenzionalnog polja smeštenog po kolonama data je izrazom: LR0R+c*[(j-1)*n + (i-1)], gde je n broj vrsta. Analogno, adresa elementa A[i,j] dvodimenzionalnog polja smeštenog po vrstama data je izrazom: LR0R+c*[(i-1)*n + (j-1)]. Analogno se smeštaju i višedimenzionalna polja u memoriju. 1. NCP koji sa standardnog ulaza učitava raspored 8 topova na šahovskoj tabli. Raspored se učitava u formi 8 linija sa po 8 brojeva po liniji. Ako na datom polju nema topa, učitava se 0, a inače 1. Program mora da ispita validnost unetog rasporeda ( da li su učitani brojevi ili 0 ili 1, da li ima 8 topova) i ispita da li se u datom rasporedu dva topa tuku. #include <stdio.h> #include <stdlib.h> main(){ int tabla[8][8]; /*matrica nula i jedinica cuva raspored 8 topova na tabli */ int suma; /* pamti se suma reda/kolone kao test osobina iz zahteva zadatka */ int i,j; /*brojaci u petljama */ /*ucitavanje podataka o rasporedu topova uz sumiranje broja topova i u slucaju greske stampa se odgovarajuca poruka i okoncava programa */ suma=0; for (i=0; i<8; i++ ) for (j=0; j<8; j++){ scanf("%d", &tabla[i][j]); /*test korektnosti ulaza */ if (tabla[i][j]!=0 && tabla[i][j]!=1 ){ printf ("\nnekorektni ulazni podaci o rasporedu topova\n"); exit(exit_failure); 1

suma=suma + tabla[i][j]; /*greska je ako je broj topova na tabli razlicit od 8 */ if(suma!=8){ printf ("\nnekorektni ulazni podaci o broju topova\n"); exit(exit_failure); /*proveravanje da li se dva topa nalaze u istom redu, tj. da li je suma clanova nekog reda veca od 1 */ for(i=0;i<8;i++){ suma=0; for (j=0;j<8;j++) suma+=tabla[i][j]; if (suma >1 ) { printf ("\ntopovi se tuku\n"); exit(exit_success); /*proveravanje da li se dva topa nalaze u istoj koloni, tj. da li je suma clanova neke kolone veca od 1 */ for(j=0;j<8;j++) { suma=0; for (i=0;i<8;i++) suma+=tabla[i][j]; if (suma >1 ) { printf ("\ntopovi se tuku\n"); exit(exit_success); /*inace se topovi ne tuku */ printf ("\ntopovi se ne tuku\n"); exit(exit_success); 1.2. 2BSTEK 1.2.1. 6BDEFINICIJE I STUKTURA Stek (stack) ili magacin je jedna od najznačajnijih linearnih i dinamičkih struktura podataka. Stavljanje (upis) ili brisanje (čitanje) elemenata se vrši samo na jednom kraju. Operacija stavljanja se naziva PUSH, a brisanja POP. Stek se prazni i puni po tzv. LIFO strategiji. #define MAXSTACKLEN 100 /* maksimalna dubina steka */ int stack[maxstacklen];/*vrednost steka */ int stackpointer;/*naredna slobodna pozicija na steku */ /* push: gurni na stek */ void push( int arg ){ if( stackpointer < MAXSTACKLEN ) stack[stackpointer++] = arg; else printf("greska: stek je pun, nemoguce je smestiti %g\n", arg); /* pop: skini sa steka*/ int pop( void ){ 2

if( stackpointer > 0 ) return stack[--stackpointer]; else{ printf("greska: stek je prazan\n" ); return 0; int top(void){ if(stackpointer > 0) return stack[stackpointer-1]; else{ printf("greska: stek je prazan\n"); return 0; 10BOpis zadatka: Za aritmetičke izraze kao što su T2+3T, T2+3*4T, T(2+3)*4T, itd. sa kojima se tipično susrećemo kako u matematici tako i u programiranju, kažemo da su zapisani u Tinfiksnoj formit, s obzirom da se operator nalazi TizmeđuT operanada. Najveća mana ovakvog zapisa leži u činjenici da je neophodno uspostaviti konvencije o TprioritetuT pojedinih operatora (npr. konvenciju da množenje ima veći prioritet u odnosu na sabiranje), i eventualno koristiti zagrade za promenu prioriteta. U računarstvu je od velikog značaja jedan posve drugačiji zapis aritmetičkih izraza, poznat pod imenom TpostfiksnaT ili Tobrnuta poljska notacijat, u kojem se operatori navode TnakonT operanada (naziv obrnuta poljska notacija dat je u čast poljskog matematičara Jana Lukasiewitza, koji je predložio upravo obrnuti princip - da se operatori zapisuju TispredT operanada). Na primer, prethodna tri izraza zapisana u infiksnoj notaciji, u obrnutoj poljskoj notaciji zapisuju se ovako: 2 3 + 2 3 4 * + 2 3 + 4 * Izračunavanje izraza u obrnutoj poljskoj notaciji izvodi se tako da se svaki operand na koji se naiđe dodaje na kraj liste (koja je na početku prazna), dok se prilikom nailaska na binarni operator poslednja dva elementa iz liste brišu i zamenjuju rezultatom operacije (sličan princip može se primeniti i na n-arne operatore). Broj koji na kraju izračunavanja ostane u listi predstavlja rezultat izračunavanja (taj broj mora biti jedinstven ako je izraz bio ispravan). Uzmimo na primer, sledeći izraz zapisan u obrnutoj poljskoj notaciji: 3 5 6 4 - * 6 + * 2 / Izračunavanje ovog izraza teklo bi ovako: 3 3 5 3 5 6 3 5 6 4 3 5 2 T6 i 4 su zamijenjeni sa 6-4=2 3 10 T5 i 2 su zamijenjeni sa 5*2=10 3

3 10 6 3 16 T10 i 6 su zamijenjeni sa 10+6=16 48 T3 i 16 su zamijenjeni sa 3*16=48 48 2 24 T48 i 2 su zamijenjeni sa 48/2=24 Dakle, rezultat izračunavanja je 24. Jedna od glavnih prednosti obrnute poljske notacije leži u činjenici da nije potrebno voditi računa o prioritetu operacija, kao i da je TsvakiT izraz moguće zapisati Tbez upotrebe zagradat. Na primer, izraz koji bi se u infiksnom obliku zapisao kao ((3 + 5) / (7-2) + 4 / (8-5)) / (3 + 5 * (4 / (7-2))) u obrnutoj poljskoj notaciji zapisuje se kao 3 5 + 7 2 - / 4 8 5 - / + 3 5 4 7 2 - / * + / Stoga, kompajleri većine programskih jezika interno prevode sve aritmetičke izraze u obrnutu poljsku notaciju pre bilo kakve dalje obrade. Vaš zadatak je da napravite program koji aritmetičke izraze u infiksnom obliku koji se sastoje od jednoslovnih promjenljivih (a-z), četiri računske operacije (T+T, T-T, T*T eventualno zagrada, pretvori u obrnutu poljsku notaciju. i T/T), i 11BUlazna datoteka: U prvom i jedinom redu ulazne tekstualne datoteke TRPN.INT nalazi se niz znakova koji predstavlja aritmetički izraz u infiksnoj notaciji koji treba pretvoriti u postfiksnu odnosno obrnutu poljsku notaciju. Ispravan aritmetički izraz sme sadržavati samo jednoslovne promenljive pisane malim slovima (od "a" do "z"), binarne operatore "T+T", "T-T", "T*T" i "T/T" kao i male zagrade "(" i ")" za promenu prioriteta operacija. Ispravan aritmetički izraz neće sadržati nikakve razmake. 12BIzlazna datoteka: Ukoliko ulazna datoteka sadrži ispravan aritmetički izraz u infiksnoj notaciji, tada u prvi i jedini red izlazne tekstualne datoteke TRPN.OUTT treba upisati niz znakova koji predstavlja aritmetički izraz u obrnutoj poljskoj notaciji. Ovaj izraz sastoji se od niza znakova koji smeju sadržavati samo mala slova (od "a" do "z") i binarne operatore "T+T", "T-T", "T*T" i "T/T". Nikakvi razmaci u izrazu nisu dozvoljeni. Ukoliko ulazna datoteka ne sadrži ispravan aritmetički izraz, u izlaznu datoteku treba samo ispisati tekst. NEISPRAVAN IZRAZ 13BPrimeri: TRPN.IN x+y+z TRPN.OUT xy+z+ TRPN.IN x+(y+z) TRPN.OUT xyz++ TRPN.IN x+y*z TRPN.OUT xyz*+ TRPN.IN (x+y)*z TRPN.OUT xy+z* TRPN.IN x*(y+z TRPN.OUT NEISPRAVAN IZRAZ 4

T RPN.IN a+b/c+d TRPN.OUT abc/+d+ TRPN.IN (a+b)/(c+d) TRPN.OUT ab+cd+/ TRPN.IN x*(y+z*(a+b*(c-d))/e) TRPN.OUT xyzabcd-*+*e/+* /****************************************** * IZRACUNAVANJE IZRAZA KOJI JE ZADAT U * * INVERZNOJ POLJSKOJ NOTACIJI * *******************************************/ int computepolish(char izraz[]){ char symbol; int sum,n,i; n=(int)strlen(izraz); i=0; while (i<n){ symbol=izraz[i]; if((symbol - '0')>=0 && (symbol - '0')<=9){ push(symbol-'0'); if ( symbol == '+' symbol == '-' symbol == '*' symbol == '/'){ int first, second; first = pop(); second = pop(); switch(symbol){ case '+': sum = first + second; break; case '-': sum = second - first; break; case '*': sum = second * first; break; case '/': sum = second / first; break; push(sum); i++; return(top()); 5

/* PREVODJENJE IZRAZA IZ INFIKS U POSTFIKS FORMU */ #include <stdio.h> #include <stdlib.h> #include <io.h> #include <string.h> int Priority(char Operator) { if(operator=='*' Operator=='/') return 2; else if(operator=='+' Operator=='-') return 1; else return 0; char *Compile(char *Expr) { static char *Error="NEISPRAVAN IZRAZ"; static char Comp[256]=""; char Last=0,Ch,Ch1,Stack[256]=""; int FindFlag,VarFlag=0,SSPtr=0,CompLen=0,SynError; int I,Parenths=0,Balance=0; for(i=0;i < (int)strlen(expr);i++) { Ch=Expr[I]; SynError=1; if(ch>='a' && Ch<='z' &&!VarFlag) { VarFlag=1; SynError=0; Balance++; Comp[CompLen++]=Ch; else VarFlag=0; if(priority(ch)) { if(priority(last) Last=='(') return Error; while(1) { SynError=0; Ch1=Stack[SSPtr-1]; if(!ssptr Ch1=='(' Priority(Ch)>Priority(Ch1)) { Stack[SSPtr++]=Ch; break; Comp[CompLen++]=Ch1; SSPtr--; Balance-=(Ch1=='+' Ch1=='-' Ch1=='*' Ch1=='/'); if(ch=='(') { Stack[SSPtr++]='('; SynError=0; Parenths++; if(ch==')'&&!(synerror=--parenths<0)) while((ch1=stack[--ssptr])!='(') { Comp[CompLen++]=Ch1; Balance-=(Ch1=='+' Ch1=='-' Ch1=='*' Ch1=='/'); if(synerror) return Error; Last=Ch; if(parenths SynError) return Error; for(i=ssptr-1;i>=0;i--) { Ch=Comp[CompLen++]=Stack[I]; Balance-=(Ch=='+' Ch=='-' Ch=='*' Ch=='/'); if(balance!=1) return Error; Comp[CompLen]=0; return Comp; int main(void) { char Str[256]; //ifstream InFile("RPN.IN"); ofstream OutFile("RPN.OUT"); //InFile>>Str; OutFile<<Compile(Str); FILE *f,*g; f=fopen("rpn.in","r"); g=fopen("rpn.out","w"); fscanf(f,"%s",str); fprintf(g,"%s",compile(str)); fclose(f);fclose(g); return 0; 6

2. Rad sa stekom nepoznatok kapaciteta /* rad sa stekom unapred nepoznatog kapaciteta */ #include <stdio.h> #include <stdlib.h> typedef struct elem { int broj; struct elem *sled; Elem; typedef Elem *Stek; Stek stvori (void); /* Stvaranje praznog steka. */ void stavi (Stek *stk, int b); /* Stavljanje broja na stek. */ int uzmi (Stek *stk); /* Uzimanje broja sa steka. */ int prazan (Stek stk); /* Da li je stek prazan? */ void pisi (Stek stk); /* Ispisivanje sadrzaja steka. */ void prazni (Stek *stk); /* Praznjenje steka. */ void unisti (Stek *stk); /* Unistavanje steka. */ int main () { Stek stk = stvori (); int b, izbor, kraj = 0; while (! kraj) { printf ("\n1. Smestaj podataka na stek\n" "2. Skidanje podatka sa steka\n" "3. Ispisivanje sadrzaja steka\n" "4. Praznjenje steka\n" "0. Zavrsetak rada\n\n" "Vas izbor? " ); scanf ("%d", &izbor); switch (izbor) { case 1: /* podatak na stek: */ printf ("Broj? "); scanf ("%d", &b); stavi (&stk, b); break; case 2: /* podatak sa steka: */ if (! prazan (stk)) printf ("Broj= %d\n", uzmi (&stk)); else printf ("*** Stek je prazan! ***\a\n"); break; case 3: /* Ispisivanje sadrzaja steka: */ printf ("Stek= "); pisi (stk); putchar ('\n'); break; case 4: /* Praznjenje steka: */ prazni (&stk); break; case 0: /* Zavrsetak rada: */ kraj = 1; break; default: /* Pogresan izbor: */ printf ("*** Neozvoljeni izbor! ***\a\n"); break; return 0; Stek stvori () { return NULL; /* Stvaranje praznog steka. */ void stavi (Stek *stk, int b) { /* Stavljanje broja na stek. */ Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = *stk; *stk = novi; int uzmi (Stek *stk) { /* Uzimanje broja sa steka. */ Elem *stari; int b; 7

if (*stk == NULL) exit (2); b = (*stk)->broj; stari = *stk; *stk = (*stk)->sled; free (stari); return b; int prazan (Stek stk) { return stk == NULL; /* Da li je stek prazan? */ void pisi (Stek stk) { Elem *tek; /* Ispisivanje sadrzaja steka. */ for (tek=stk; tek; tek=tek->sled) printf ("%d ", tek->broj); void prazni (Stek *stk) { /* Praznjenje steka. */ while (*stk) { Elem *stari=*stk; (*stk)=(*stk)->sled; free(stari); void unisti (Stek *stk) { prazni (stk); /* Unistavanje steka. */ 7BPrimena steka rekurzija Prilikom rekurzije moraju se poštovati dva osnovna principa: 1) Svaki sledeći poziv mora voditi ka konačnom rešenju problema 2) Mora postojati uslov za završetak procesa #define DIM 1000 int faktorijelrekurzivno(int n){ int retv,pom; if(n==1) retv=1; else{ pom=faktorijelrekurzivno(n-1); retv=n*pom; return retv; int faktorijelnerekurzivno(int n){ int top=-1, stn[dim],stretv[dim],stadr[dim],stpom[dim]; int retv,adr,pom; step1: if(n==1){ retv=1; stretv[top]=retv; else{ step2: //prevodjenje poziva faktorijelrekurzivno(n-1) top++; stn[top] = n; stretv[top] = retv; stpom[top] = pom; stadr[top] = 3; //postavi paramertre na nove vrednosti n--; goto step1; step3: pom = retv; 8

retv = n*pom; stretv[top]=retv; //prevodjenje return if(top == -1) return retv; else{ n = stn[top]; retv = stretv[top]; pom = stpom[top]; adr = stadr[top]; top--; if(adr == 3) goto step3; //posto je samo jedan rekurzivan poziv //jedno je i mesto odakle se posle pozivna nastavlja funkcija //goto step3 void move(int d, char f, char t) { /* move disk d from peg f to peg t */; printf("moving disk %d : %c --> %c\n", d, f, t); void hanoi(int h, char f, char t, char r) { if (h > 0) { hanoi(h-1, f, r, t); move (h, f, t); hanoi(h-1, r, t, f); void hanoinerekurzivno(int n, char poc, char pom, char kraj){ int stn[dim], stpoc[dim], stpom[dim], stkraj[dim], stadr[dim]; int top=-1, adr, tmp; step1: if(n==1){ printf("\n %c -> %c ", poc, kraj); goto step5; //prevodjenje poziva hanoi(n-1,poc,kraj,pom); top++; stn[top] = n; stpoc[top] = poc; stpom[top] = pom; stkraj[top] = kraj; stadr[top] = 3; //setuj parametre na nove vrednosti n--; poc = poc; tmp = pom; pom = kraj; kraj = tmp; goto step1; step3: printf("\n %c -> %c ", poc, kraj); //prevodjenje poziva hanoi(n-1,pom,poc,kraj) 9

step5: top++; stn[top] = n; stpoc[top] = poc; stpom[top] = pom; stkraj[top] = kraj; stadr[top] = 5; //setuj parametre na nove vrednosti n--; tmp = poc; poc = pom; pom = tmp; kraj = kraj; goto step1; if(top == -1) return; else{ n = stn[top]; poc = stpoc[top]; pom = stpom[top]; kraj = stkraj[top]; adr = stadr[top]; top--; if(adr == 3) goto step3; if(adr == 5) goto step5; 2.1. 3BRED Kod steka se sva umetanja i brisanja izvršavaju na kraju koji se naziva vrh (TOP), dok se kod reda sva umetanja izvršavaju na kraju KRAJ, a sva brisanja na drugom kraju reda, tj. početku Čelo. Redovi su poznati kao FIFO memorije. Red S možemo implementirati kao konačan niz S[0..n-1] i pri tome se koriste dva podatka, CELO i KRAJ da bi se oznčile granice reda. Ako je CELO < KRAJ tada se red sastoji od S[CELO]... S[KRAJ-1]. U suprotnom, ako je CELO > KRAJ, tada se red sastoji od S[CELO],...,S[n-1],S[0],...,S[KRAJ-1], i ako je CELO = KRAJ, tada je red prazan. 10

Definicija 2.2. 4BLANČANE LISTE 2.2.1. 8B Lančana lista, za razliku od prethodnih struktura koristi lančani (spregnuti) način zauzeća memorije. Prednosti korišćenja lančane liste: - Količina rezervisane memorije ne mora biti unapred zadata i fiksirana. Tačan iznos zauzete memorije će zavisiti isključivo od količine podataka koji se obrađuju. - Moguće je brzo i često brisanje i umetanje podataka. Elementi lančane liste nisu memorisani u uzastopnim memorijskim lokacijama, već svaki element eksplicitno ukazuje na naredni element u memoriji. Postoji nekoliko tipova listi: 1) jednostruko spregnuta lista 2) dvostruko spregnuta lista 3) kružna lista 2.2.2. 9BJEDNOSTRUKO SPREGNUTA LINEARNA LISTA Svaki element ove strukture sadrži dva polja: podatak i pokazivač na naredni element u listi. Glava liste je pokazivač koji sadrži adresu prvog elementa liste. /* Rad sa jednostruko spregnutom listom - iterativne verzije funkcija za rad sa povezanom listom */ #include <stdio.h> #include <stdlib.h> typedef struct elem { int broj; struct elem *sled; Elem; /*Element liste*/ int duz (Elem *lst); /* Broj elemenata liste. */ void pisi (Elem *lst); /* Ispisivanje liste. */ Elem *na_pocetak (Elem *lst, int b); /* Dodavanje na pocetak. */ Elem *na_kraj (Elem *lst, int b); /* Dodavanje na kraj. */ Elem *citaj1 (int n); /* Citanje liste stavljajuci brojeve na pocetak. */ Elem *citaj2 (int n); /* Citanje liste stavljajuci brojeve na kraj. */ Elem *umetni (Elem *lst, int b); /* Umetanje u uredjenu listu. */ void brisi (Elem *lst); /* Brisanje svih elemenata liste. */ Elem *izostavi (Elem *lst, int b); /* Izostavljanje svakog pojavljivanja. */ void main () { Elem *lst = NULL; int kraj = 0, izbor, broj, n; while (!kraj) { printf ("\n1. Dodavanje broja na pocetak liste\n" "2. Dodavanje broja na kraj liste\n" "3. Umetanje broja u uredjenu listu\n" 11

"4. Izostavljanje broja iz liste\n" "5. Brisanje svih elemenata liste\n" "6. Citanje uz obrtanje redosleda brojeva\n" "7. Citanje uz cuvanje redosleda brojeva\n" "8. Odredjivanje duzine liste\n" "9. Ispisivanje liste\n" "0. Zavrsetak rada\n\n" "Vas izbor? " ); scanf ("%d", &izbor); switch (izbor) { case 1: case 2: case 3: case 4: printf ("Broj? "); scanf ("%d", &broj); switch (izbor) { case 1: /* Dodavanje broja na pocetak liste: */ lst = na_pocetak (lst, broj); break; case 2: /* Dodavanje broja na kraj liste: */ lst = na_kraj (lst, broj); break; case 3: /* Umetanje broja u uredjenu listu: */ lst = umetni (lst, broj); break; case 4: /* Izostavljanje broja iz liste: */ lst = izostavi (lst, broj); break; break; case 5: /* Brisanje svih elemenata liste: */ brisi (lst); lst = NULL; break; case 6: case 7: /* Citanje liste: */ printf ("Duzina? "); scanf ("%d", &n); printf ("Elementi? "); brisi (lst); switch (izbor) { case 6: /* uz obrtanje redosleda brojeva: */ lst = citaj1 (n); break; case 7: /* uz cuvanje redosleda brojeva: */ lst = citaj2 (n); break; break; case 8: /* Odredjivanje duzine liste: */ printf ("Duzina= %d\n", duz (lst)); break; case 9: /* Ispisivanje liste: */ printf ("Lista= "); pisi (lst); putchar ('\n'); break; case 0: /* Zavrsetak rada: */ kraj = 1; break; default: /* Pogresan izbor: */ printf ("*** Neozvoljeni izbor! ***\a\n"); break; /* Definicije funkcija za obradu lista (iterativno). */ int duz (Elem *lst) { /* Broj elemenata liste. */ int n = 0; while (lst){ n++; lst = lst->sled; return n; void pisi (Elem *lst){ /* Ispisivanje liste. */ while(lst){ printf("%d ",lst->broj); 12

lst = lst -> sled; Elem *na_pocetak(elem *lst, int b){ /* Dodavanje na pocetak. */ Elem *novi = malloc(sizeof(elem)); novi->broj = b; novi->sled = lst; return novi; Elem *na_kraj (Elem *lst, int b) { /* Dodavanje na kraj. */ Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = NULL; if (!lst) return novi; else { Elem *tek = lst; while (tek->sled) tek = tek->sled; tek->sled = novi; return lst; Elem *citaj1 (int n) { /* Citanje liste stavljajuci brojeve na pocetak. */ Elem *prvi = NULL; int i; for (i=0; i<n; i++) { Elem *novi = malloc (sizeof(elem)); scanf("%d", &novi->broj); novi->sled = prvi; prvi = novi; return prvi; Elem *citaj2 (int n) { /* Citanje liste stavljajuci brojeve na kraj. */ Elem *prvi = NULL, *posl = NULL; int i; for (i=0; i<n; i++) { Elem *novi = malloc (sizeof(elem)); scanf ("%d", &novi->broj); novi->sled = NULL; if (!prvi) prvi = novi; else posl->sled = novi; posl = novi; return prvi; Elem *umetni (Elem *lst, int b) { /* Umetanje u uredjenu listu. */ 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 brisi (Elem *lst) { /* Brisanje svih elemenata liste. */ 13

while(lst){ Elem *stari = lst; lst = lst->sled; free (stari); Elem *izostavi(elem *lst, int b){ /* Izostavljanje svakog pojavljivanja. */ Elem *tek = lst, *pret = NULL; while(tek) if (tek->broj!= b){ pret = tek; tek = tek->sled; else { Elem *stari = tek; tek = tek->sled; if (!pret) lst = tek; else pret->sled = tek; free (stari); return lst; /* Rad sa povezanom listom - REKURZIVNE verzije funkcija za rad sa povezanom listom; */ #include <stdio.h> #include <stdlib.h> typedef struct elem { int broj; struct elem *sled; Elem; /*Element liste*/ int duz (Elem *lst); /* Broj elemenata liste. */ void pisi (Elem *lst); /* Ispisivanje liste. */ Elem *na_pocetak (Elem *lst, int b); /* Dodavanje na pocetak. */ Elem *na_kraj (Elem *lst, int b); /* Dodavanje na kraj. */ Elem *citaj1 (int n); /* Citanje liste stavljajuci brojeve na pocetak. */ Elem *citaj2 (int n); /* Citanje liste stavljajuci brojeve na kraj. */ 14

Elem *umetni (Elem *lst, int b); /* Umetanje u uredjenu listu. */ void brisi (Elem *lst); /* Brisanje svih elemenata liste. */ Elem *izostavi (Elem *lst, int b); /* Izostavljanje svakog pojavljivanja. */ void main () { Elem *lst = NULL; int kraj = 0, izbor, broj, n; while (!kraj) { printf ("\n1. Dodavanje broja na pocetak liste\n" "2. Dodavanje broja na kraj liste\n" "3. Umetanje broja u uredjenu listu\n" "4. Izostavljanje broja iz liste\n" "5. Brisanje svih elemenata liste\n" "6. Citanje uz obrtanje redosleda brojeva\n" "7. Citanje uz cuvanje redosleda brojeva\n" "8. Odredjivanje duzine liste\n" "9. Ispisivanje liste\n" "0. Zavrsetak rada\n\n" "Vas izbor? " ); scanf ("%d", &izbor); switch (izbor) { case 1: case 2: case 3: case 4: printf ("Broj? "); scanf ("%d", &broj); switch (izbor) { case 1: /* Dodavanje broja na pocetak liste: */ lst = na_pocetak (lst, broj); break; case 2: /* Dodavanje broja na kraj liste: */ lst = na_kraj (lst, broj); break; case 3: /* Umetanje broja u uredjenu listu: */ lst = umetni (lst, broj); break; case 4: /* Izostavljanje broja iz liste: */ lst = izostavi (lst, broj); break; break; case 5: /* Brisanje svih elemenata liste: */ brisi (lst); lst = NULL; break; case 6: case 7: /* Citanje liste: */ printf ("Duzina? "); scanf ("%d", &n); printf ("Elementi? "); brisi (lst); switch (izbor) { case 6: /* uz obrtanje redosleda brojeva: */ lst = citaj1 (n); break; case 7: /* uz cuvanje redosleda brojeva: */ lst = citaj2 (n); break; break; case 8: /* Odredjivanje duzine liste: */ printf ("Duzina= %d\n", duz (lst)); break; case 9: /* Ispisivanje liste: */ printf ("Lista= "); pisi (lst); putchar ('\n'); break; case 0: /* Zavrsetak rada: */ kraj = 1; break; default: /* Pogresan izbor: */ printf ("*** Neozvoljeni izbor! ***\a\n"); break; /* Definicije funkcija za obradu lista (REKURZIVNO). */ 15

int duz (Elem *lst) { /* Broj elemenata liste. */ return lst? duz (lst->sled) + 1 : 0; void pisi (Elem *lst) { /* Ispisivanje liste. */ if (lst) { printf ("%d ", lst->broj); pisi (lst->sled); Elem *na_pocetak (Elem *lst, int b) { /* Dodavanje na pocetak. */ Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = lst; return novi; Elem *na_kraj (Elem *lst, int b) { /* Dodavanje na kraj. */ if (!lst) { lst = malloc (sizeof(elem)); lst->broj = b; lst->sled = NULL; else lst->sled = na_kraj (lst->sled, b); return lst; Elem *citaj1 (int n) { /* Citanje liste uz obrtanje redosleda. */ if (n == 0) return NULL; else { Elem *novi = malloc (sizeof(elem)); novi->sled = citaj1 (n - 1); scanf ("%d", &novi->broj); return novi; Elem *citaj2 (int n) { /* Citanje liste uz cuvanje redosleda. */ if (n == 0) return NULL; else { Elem *novi = malloc (sizeof(elem)); scanf ("%d", &novi->broj); novi->sled = citaj2 (n - 1); return novi; Elem *umetni (Elem *lst, int b) { /* Umetanje u uredjenu listu. */ if (!lst lst->broj >= b) { Elem *novi = malloc (sizeof(elem)); novi->broj = b; novi->sled = lst; return novi; else { lst->sled = umetni (lst->sled, b); return lst; void brisi (Elem *lst) { /* Brisanje svih elemenata liste. */ if (lst) { brisi (lst->sled); free (lst); Elem *izostavi (Elem *lst, int b){ /* Izostavljanje svakog pojavljivanja. */ if (lst) { if (lst->broj!= b) { lst->sled = izostavi (lst->sled, b); 16

else { Elem *stari = lst; lst = izostavi (lst->sled, b); free (stari); return lst; 2.2.3. KRUŽNO SPREGNUTA LINEARNA LISTA Kod ovog tipa liste pokazivač poslednjeg elementa nema NULL vrednost već ukazuje na prvi element liste. Prednosti ovog tipa liste su: - Svakom elementu se može pristupiti polazeći od bilo kog elementa liste. - Jednostavnije pronalaženje elemenata liste. - Efikasnije operacije dodavanja i brisanja elemenata iz liste. Kod ovog tipa liste neophodno je znati prvi ili poslednji element. To možemo rešiti na dva načina: 1) Pokazivač na glavu liste 2) Označavanje početnog elementa liste. Npr. ostaviti prazno polje za podatak, ili u njega upisati specijalni simbol... itd. 2.2.4. DVOSTRUKO POVEZANA LINEARNA LISTA Kod ovog tipa listi, svaki element ima dva pokazivača koji ukazuju na prethodni i naredni element (levi i desni ukazivač). Levi ukazivač krajnjeg levog i desni pokazivač krajnjeg desnog elementa su NULL. 17

2. NCP koji iz neprazne datoteke broj.txt ucitava paran broj celih brojeva x[1], x[2],...,x[n], gde n nije unapred poznato. Ispisati poruku na standardni izlaz da li vazi da x[1]==x[n], x[2]==x[n-1],..., x[k]=x[k+1], k=1..n/2 #include <stdio.h> #include <stdlib.h> typedef struct listacv dvlista; /*dvostruko povezana linearna lista*/ struct listacv{ int broj; /*informaciono polje je clan niza x*/ dvlista *sledeci, *prethodni; ; dvlista *ubaci(dvlista *kraj, int broj){ dvlista *novi; /*novi cvor za umetanje u listu*/ novi=(dvlista *)malloc(sizeof(dvlista)); /*alokacija memorije za novi cvor liste*/ novi->broj=broj; /*inicijalizacija polja broj u cvoru novi */ 18

novi->sledeci=null; novi->prethodni=kraj; /*novi element se dodaje na kraj postojece liste*/ kraj->sledeci=novi; /* do tada poslednji cvor kraj je ispred clana novi*/ kraj=novi; /*poslednji dodat element je novi kraj liste*/ return kraj; main() { dvlista *prvi, *kraj; /*prvi i poslednji cvor dvostruke liste*/ int n; /*broj ucitanih celih brojeva*/ int broj; /*tekuci broj sa ulaza*/ int jednak; /*indikator jednakosti dva clana - cuva vrednost 0 ili 1 */ FILE *ulaz; int i; /*brojacka promenljiva*/ /*otvaranje datoteke za citanje i upis brojeva iz datoteke u dvostruku povezanu listu */ ulaz=fopen("broj.txt", "r"); fscanf(ulaz, "%d", &broj); /*kreiranje prvog cvora liste za prvi ucitan broj */ prvi=(dvlista*)malloc(sizeof(dvlista)); prvi->broj=broj; prvi->sledeci=null; prvi->prethodni=null; kraj=prvi; n=1; //za sada ucita je samo jedan clan /*formiranje liste od brojeva koji se ucitavaju sve do kraja datoteke - feof(ulaz) */ while (!feof(ulaz)) { fscanf(ulaz, "%d", &broj); kraj=ubaci (kraj, broj); n++; fclose(ulaz); /*testiranje jednakih parova uz pomeranje tekuceg prvog clana i tekuceg poslednjeg clana ka sredini liste*/ jednak=1; for(i=1; i<=n/2 && jednak; i++) { jednak=jednak&&(prvi->broj==kraj->broj); prvi=prvi->sledeci; /*pomeranje ka sredini liste */ kraj=kraj->prethodni; /*pomeranje ka sredini liste */ printf("za unete broje jednakost "); if(!jednak) printf("ne "); printf("vazi\n"); return 0; 2.2.5. PRIMENE SPREGNUTIH LINEARNIH LISTI Prikaz polinoma Pretpostavimo da imamo polinom od tri promenljive: 3X 2 + 4XY + Y 2 + XYZ Svaki element liste koji prikazuje jedan član polinoma dat je na sledećoj slici: 19

Spregnuta lista za prikaz ovog polinoma izgledala bi: Odgovarajuća struktura elementa bi bila: typedef struct elem element; struct elem{ int expx; int expy; int expz; int koef; element *naredni; 3. NCP-e za sabiranje, oduzimanje i množenje polinoma jedne promenljive. #include <stdio.h> #include <stdlib.h> #include <math.h> struct pnode{ double coef; long power; struct pnode *link; ; typedef struct pnode poly; #define COEF(a)((a)->coef) #define POWER(a)((a)->power) #define LINK(a)((a)->link) poly *addelem(poly *p, double coef, long pow){ poly *c,*newel,*pret=null; c = p; while(c && POWER(c) > pow){ pret=c; c = LINK(c); if(!c POWER(c) < pow){ newel = (poly*)malloc(sizeof(poly)); COEF(newel) = coef; POWER(newel) = pow; LINK(newel) = c; if(!pret) p = newel; else LINK(pret) = newel; return p; if(power(c) == pow){ COEF(c) += coef; return p; 20

poly *create(){ int pow; double c; poly *p=null; printf("\nunesite polinom pocev od najveceg stepena:\n"); while(1){ printf("\nkoeficijent: "); scanf("%lf",&c); printf("\nstepen: "); scanf("%d",&pow); if(c == 0) break; p = addelem(p,c,pow); if(pow == 0) break; return p; void display(poly *p){ poly *cur=p; if(cur){ printf(" %c %.2f * X^%d",COEF(cur)<0?'-':' ',fabs(coef(cur)),power(cur)); cur=link(cur); while(cur!= NULL){ printf(" %c %.2f * X^%d",COEF(cur)<0?'-':'+',fabs(COEF(cur)),POWER(cur)); cur=link(cur); poly *polyadd(poly* p1, poly* p2){ poly *p, *res=null; p=p1; while(p){ res=addelem(res,coef(p),power(p)); p=link(p); p=p2; while(p){ res=addelem(res,coef(p),power(p)); p=link(p); return res; poly *polysub(poly* p1, poly* p2){ poly *p, *res=null; p=p1; while(p){ res=addelem(res,coef(p),power(p)); p=link(p); p=p2; while(p){ res=addelem(res,-coef(p),power(p)); p=link(p); 21

return res; poly *polymul(poly* p1, poly* p2){ poly *pom1,*pom2,*res=null; pom1=p1; while(pom1){ pom2=p2; while(pom2){ res=addelem(res,coef(pom1)*coef(pom2),power(pom1)+power(pom2)); pom2=link(pom2); pom1=link(pom1); return res; poly *polydif(poly* p1){ poly *pom1,*res=null; pom1=p1; while(pom1){ if(power(pom1)!=0) res=addelem(res,coef(pom1)*power(pom1),power(pom1)-1); pom1=link(pom1); return res; void brisi(poly *p){ poly *stari; while(p){ stari=p; p=link(p); free(stari); void main(){ int ch; poly *poly1,*poly2,*poly3; poly1=poly2=poly3=null; printf("\nunesite prvi polinom:\n"); poly1=create(); display(poly1); poly2=create(); display(poly2); while(1){ printf("************************" "\nodaberi operaciju:\n" "1.Sabiranje\n" "2.Oduzimanje\n" "3.Mnozenje\n" "4.Izvod\n" "5.Izlaz\n"); scanf("%d",&ch); switch(ch){ case 1: poly3=polyadd(poly1,poly2); break; case 2: poly3=polysyb(poly1,poly2); 22

break; case 3: poly3=polymul(poly1,poly2); break; case 4: poly3=polydif(poly1); break; default: exit(1); brisi(poly1); brisi(poly2); brisi(poly3); RETKO POSEDNUTE MATRICE Realizuje se preko spregnutih listi i ima za cilj smanjenje broja izračunavanja, kao i smanjenje potrebne memorije za čuvanje sturkture. Jedna moguća reprezentacija dvodimenzionalne retko posednute matrice bi bila preko jedne spregnute liste za svaki red i svaku kolonu matrice. Svaka od ovih listi ima zaglavlje, tj. glavu. Svakom nenultom mestu u matrici odgovara jedan čvor oblika: struct cvor { int red; int kolona; int vrednost; struct cvor *nar_u_kol; struct cvor *nar_u_vrsti; /* Implementacija dinamickih kvadratnih matrica preko pokazivaca na niz pokazivaca na kolone */ #include <stdio.h> 23

#include <stdlib.h> /* Tip elemenata matrice ce biti float */ typedef float tip; /* Funkcija alocira matricu dimenzije n*n */ tip** allocate(int n){ tip **m; int i; /* Alocira se niz pokazivaca na kolone */ m=(tip**)malloc(n*sizeof(tip*)); for (i=0; i<n; i++) /* Alociraju se nizovi brojeva koji predstavljaju kolone */ m[i]=(tip*)malloc(n*sizeof(tip)); return m; /* Funkcija vrsi dealociranje date matrice dimenzije n */ void deallocate(tip** m, int n){ int i; /* Uklanjaju se kolone */ for (i=0; i<n; i++) free(m[i]); /* Uklanja se niz pokazivaca na kolone */ free(m); /* Funkcija ispisuje datu matricu dimenzije n */ void IspisiMatricu(tip** matrica, int n){ int i,j; for (i=0; i<n; i++){ for(j=0; j<n; j++) printf("%f\t",matrica[i][j]); printf("\n"); /* Funkcija ucitava datu matricu i njenu dimenziju */ void UnesiMatricu(tip*** matrica,int *pn){ int i,j; printf("unesite dimenziju kvadratne matrice :"); scanf("%d",pn); *matrica=allocate(*pn); for (i=0; i<*pn; i++) for(j=0; j<*pn; j++){ printf("a[%d][%d]=",i+1,j+1); scanf("%f",&((*matrica)[i][j])); /* Rekurzivna funkcija koja vrsi Laplasov razvoj - neefikasna, ali dobra vezba */ tip determinanta(tip** matrica, int n){ int i; tip** podmatrica; int det=0,znak; /* Izlaz iz rekurzije je matrica 1x1 */ if (n==1) return matrica[0][0]; /* Podmatrica ce da sadrzi minore polazne matrice */ podmatrica=allocate(n-1); znak=1; for (i=0; i<n; i++){ int vrsta,kolona; for (kolona=0; kolona<i; kolona++) for(vrsta=1; vrsta<n; vrsta++) 24

podmatrica[vrsta-1][kolona]=matrica[vrsta][kolona]; for (kolona=i+1; kolona<n; kolona++) for(vrsta=1; vrsta<n; vrsta++) podmatrica[vrsta-1][kolona-1]=matrica[vrsta][kolona]; det+=znak*matrica[0][i]*determinanta(podmatrica,n-1); znak*=-1; deallocate(podmatrica,n-1); return det; main(){ /* Matrica i njena dimenizija */ tip **matrica; int n; /* Unosi se matrica */ UnesiMatricu(&matrica,&n); /* Ispisuje se determinanta */ printf("determinanta je : %f\n",determinanta(matrica,n)); return 0; 1. NCP koji unosi sa standardnog ulaza dve realne matrice A, B i ispisuje na standardni izlaz A+B, A-B, A*B. Dimenzije matrica nisu unapred poznate. Ispisati poruke o greskama na standardni tok za poruke o gresci. #include <stdio.h> #include <stdlib.h> typedef struct { float **a; int m, n; Din_mat; /* Struktura matrice. */ Din_mat stvori (int m, int n); /* Dodela memorije. */ void unisti (Din_mat dm); /* Oslobadjanje memorije*/ Din_mat kopiraj (Din_mat dm); /* Kopiranje matrice. */ Din_mat citaj (int m, int n); /* Citanje matrice. */ void pisi (Din_mat dm, const char *frm, int max); /* Ispisivanje matrice. */ Din_mat transpon (Din_mat dm); /* Transponovana matrica*/ Din_mat zbir (Din_mat dm1, Din_mat dm2); /* Zbir matrica. */ Din_mat razlika (Din_mat dm1, Din_mat dm2); /* Razlika matrica. */ Din_mat proizvod (Din_mat dm1, Din_mat dm2); /* Proizvod matrica. */ typedef enum {MEM, DIM Greska; */ /* Kodovi poruka o gresakama. const char *poruke[] = { "Neuspela dodela memorije", /* Poruke o gresci.*/ "Neusaglasene dimenzije matrica" ; int main () { while (1) { Din_mat dm1, dm2, dm3; int m, n; printf ("Broj vrsta, broj kolona: "); scanf ("%d%d", &m, &n); if (m<=0 n<=0) break; printf ("Prva matrica: "); dm1 = citaj (m, n); printf ("Broj vrsta, broj kolona: "); scanf ("%d%d", &m, &n); if (m<=0 n<=0) break; printf ("Druga matrica: "); dm2 = citaj (m, n); if (dm1.m==dm2.m && dm1.n==dm2.n) { dm3 = zbir (dm1, dm2); printf ("ZBIR:\n"); pisi (dm3, "%8.2f", 8); 25

unisti (dm3); dm3 = razlika (dm1, dm2); printf ("RAZLIKA:\n"); pisi (dm3, "%8.2f", 8); unisti (dm3); if (dm1.n == dm2.m) { dm3 = proizvod (dm1, dm2); printf ("PROIZVOD:\n"); pisi (dm3, "%8.2f", 8); unisti (dm3); putchar ('\n'); unisti (dm1); unisti (dm2); return 0; static void greska (Greska g) { /* Ispisivanje poruke o gresci. */ fprintf (stderr, "\n*** %s! ***\n\a", poruke[g]); exit (g+1); Din_mat stvori (int m, int n) { /* Dodela memorije. */ int i; Din_mat dm; dm.m = m; dm.n = n; if ((dm.a = malloc (m * sizeof(float*))) == NULL) greska (MEM); for (i=0; i<m; i++) if ((dm.a[i] = malloc (n * sizeof(float))) == NULL) greska (MEM); return dm; void unisti (Din_mat dm) { int i; for (i=0; i<dm.m; free(dm.a[i++])); free (dm.a); /* Oslobadjanje memorije*/ Din_mat kopiraj (Din_mat dm) { /* Kopiranje matrice. */ int i, j; Din_mat dm2 = stvori (dm.m, dm.n); for (i=0; i<dm.m; i++) for (j=0; j<dm.n; j++) dm2.a[i][j] = dm.a[i][j]; return dm2; Din_mat citaj (int m, int n) { /* Citanje matrice. */ int i, j; Din_mat dm = stvori (m, n); for (i=0; i<m; i++) for (j=0; j<n; scanf("%f",&dm.a[i][j++])); return dm; void pisi (Din_mat dm, const char *frm, int max){ /* Ispisivanje matrice. */ int i, j; for (i=0; i<dm.m; i++) { for (j=0; j<dm.n; j++) { printf (frm, dm.a[i][j]); 26

putchar ((j%max==max-1 j==dm.n-1)? '\n' : ' '); if (dm.n > max) putchar ('\n'); Din_mat transpon (Din_mat dm) { /* Transponovana matrica*/ int i, j; Din_mat dm2 = stvori (dm.n, dm.m); for (i=0; i<dm.m; i++) for (j=0; j<dm.n; j++) dm2.a[j][i] = dm.a[i][j]; return dm2; Din_mat zbir (Din_mat dm1, Din_mat dm2) { /* Zbir matrica. */ int i, j; Din_mat dm3; if (dm1.m!=dm2.m dm1.n!= dm2.n) greska (DIM); dm3 = stvori (dm1.m, dm1.n); for (i=0; i<dm3.m; i++) for (j=0; j<dm3.n; j++) dm3.a[i][j] = dm1.a[i][j] + dm2.a[i][j]; return dm3; Din_mat razlika (Din_mat dm1, Din_mat dm2) { /* Razlika matrica. */ int i, j; Din_mat dm3; if (dm1.m!=dm2.m dm1.n!= dm2.n) greska (DIM); dm3 = stvori (dm1.m, dm1.n); for (i=0; i<dm3.m; i++) for (j=0; j<dm3.n; j++) dm3.a[i][j] = dm1.a[i][j] - dm2.a[i][j]; return dm3; Din_mat proizvod (Din_mat dm1, Din_mat dm2) { /* Proizvod matrica. */ int i, j, k; Din_mat dm3; if (dm1.n!=dm2.m) greska (DIM); dm3 = stvori (dm1.m, dm2.n); for (i=0; i<dm3.m; i++) for (k=0; k<dm3.n; k++) for (dm3.a[i][k]=j=0; j<dm2.n; j++) dm3.a[i][k] += dm1.a[i][j] * dm2.a[j][k]; return dm3; 27

3. Zadaci za vežbu 1. Brojeve zapisane u sistemu s bazom 3 možemo prikazati kao povezanu listu, čije ćelije su zapisi sa dve komponente: cifra, pointer na iduću ćeliju. Glava liste (header) pokazuje na najmanje značajnu cifru (cifru najmanje težine). Napišite potrebnu definiciju tipa podatka BASE3NUMBER. Zatim napišite potprogram za sabiranje dva broja zapisanih u bazi 3. 2. Data je sortirana jednostruko povezana linearna lista. Ubaciti novi element u listu, tako da ona i dalje ostane sortirana. Napisati funkcije za kreiranje i štampanje elemenata linearne liste, kao i traženu funkciju za ubacivanje elementa u listu. typedef struct cvor { int br; struct cvor* sl; CVOR; #include <stdio.h> #include <stdlib.h> typedef struct cvor{ int broj; struct cvor *sled; Cvor; void pisi (Cvor *lst); Cvor *umetni (Cvor *lst, int b,int n); void pisi (Cvor *lst) { if (lst) { printf ("%d ", lst->broj); pisi (lst->sled); Cvor *umetni (Cvor *lst, int b,int n) { Cvor *tek = lst, *pret = NULL, *novi; while(tek && tek->broj < b){ pret = tek; tek = tek->sled; novi =(Cvor*)malloc (n*sizeof(cvor)); novi->broj = b; novi->sled = tek; if(!pret) lst = novi; else pret->sled = novi; return lst; 3. Element INFO jednostruko povezane liste je tipa char* (C-string). Napisati C-funkciju 'izdvoji' koja iz ulazne jednostru ko povezane liste izdvaja u novu izlaznu jednostruko povezanu listu sve elemente čiji INFO počinje 28

sa zadatim uzorkom. Funkcija ima sledeći prototip: typedef struct _jpl { char *info; struct _jpl* link; JPL_T; JPL_T* izdvoji(jpl_t **ullista, const char *uzorak); #include <stdio.h> #include <string.h> #include <stdlib.h> typedef struct _jp1 { char *info; struct _jp1* link; JPL_T; void ucitajinfo(char **s){ *s=null; char c; int n=0; c = getchar(); if(c=='\n') c=getchar(); while((c!=' ')&&(c!='\n')){ n++; *s=(char*)realloc(*s,n*sizeof(char)); *(*s+n-1)=c; c = getchar(); *(*s+n)='\0'; JPL_T* izdvoji(jpl_t *ullista, const char *uzorak) { JPL_T *prvi = NULL, *posl = NULL; while(ullista) { if(strstr(ullista->info, uzorak)==ullista->info) { JPL_T *novi = (JPL_T *)malloc (sizeof(jpl_t)); novi->info = ullista->info; novi->link = NULL; if (!prvi) prvi = novi; else posl->link = novi; posl = novi; ullista = ullista->link; return prvi; void ispisi(jpl_t *lst){ while(lst){ printf("%s ",lst->info); lst = lst -> link; JPL_T *ucitaj (int n) { JPL_T *prvi = NULL, *posl = NULL; 29

int i; for (i=0; i<n; i++) { JPL_T *novi = (JPL_T *)malloc (sizeof(jpl_t)); ucitajinfo(&(novi->info)); novi->link = NULL; if (!prvi) prvi = novi; else posl->link = novi; posl = novi; return prvi; 4. Dat je pokazivač na kraj dvostruko povezane liste celih brojeva. Napisati funkciju koja će prvi čvor prebaciti na poslednje mesto. 5. Napisati program koji računa n-ti izvod polinoma zapisanog u obliku P(x) = a n x n +... + a 1 x + a 0. Polinom se zadaje povezanom listom gde je prvi element liste slobodan član. Štampati dobijeni rezultat. #include <stdio.h> #include <stdlib.h> struct polinom{ int stepenx; long koeficijent; struct polinom* sledeci; ; typedef struct polinom Polinom; Polinom* ucitavanjepolinoma(){ int stepen,koef; Polinom * tekuci, *start,*novi; tekuci =(Polinom*) malloc(sizeof(polinom)); start = tekuci; tekuci->sledeci = NULL; puts("unesite polinom:"); while(1){ printf("\nkoeficijent: "); scanf("%d",&koef); if(!koef) break; printf("\nstepen: "); scanf("%d",&stepen); novi = (Polinom*) malloc(sizeof(polinom)); novi->koeficijent = koef; novi->stepenx = stepen; novi->sledeci = NULL; tekuci->sledeci = novi; tekuci = novi; return start; Polinom* izvodpolinoma(polinom* pol){ Polinom* temp; temp = pol->sledeci; while(temp){ temp->koeficijent *= temp->stepenx; temp->stepenx--; temp = temp->sledeci; 30

void stampajpolinom(polinom* pol){ Polinom* temp; temp = pol->sledeci; while(temp){ if(temp->stepenx == 0){ printf("%d ",temp->koeficijent); else { printf("%da^%d ",temp->koeficijent,temp->stepenx); temp = temp->sledeci; if(temp) printf("+ "); puts(""); void ukloni(polinom* pol){ Polinom * temp; while(pol){ temp = pol; pol = pol->sledeci; free(temp); void brisiclansanulomukoeficijentu(polinom* pol){ Polinom* prvi,*drugi; prvi = pol; drugi = prvi->sledeci; while(drugi){ if(drugi->koeficijent == 0){ prvi->sledeci = drugi->sledeci; free(drugi); drugi = prvi->sledeci; else{ prvi = drugi; drugi = drugi->sledeci; void ntiizvodpolinoma(int n,polinom* pol){ int i; for(i = 0; i < n; i++){ izvodpolinoma(pol); brisiclansanulomukoeficijentu(pol); 6. Implementirati STACK pomoću jednostruko povezane liste (deklarisati potrebne tipove podataka i napisati funkcije PUSH i POP), a zatim napisati funkciju koja računa izraz zadan u postfiksnoj notaciji koristeći već implementirani STACK. 7. Implementirati jednostruko povezanu listu LIST pomoću pokazivača (deklarisati potrebne tipove podataka) čiji su elementi celi brojevi, a zatim napisati funkciju koja u datu sortiranu povezanu listu ubacuje elemente druge povezane liste, tako da lista ostaje sortirana. 31

8. U stek realizovan poljem smeštju se celobrojni podaci (int). Napisati funkcije za stavljanje novog elementa na stek i skidanje elementa sa vrha steka koje vraćaju 1 ako su uspešno obavile posao, a 0 inače. Ukoliko je prilikom skidanja nekog elementa sa steka barem 20 elemenata steka slobodno, stek treba smanjiti za 10 elemenata. Ukoliko kod stavljanja elementa na stek više nema slobodnog prostora, stek uvećati za 10 elemenata. Funkcije moraju imati prototip: int stavi(int element, int **stog, int *max, int *vrh); int skini(int *element, int **stog, int *max, int *vrh); #include <stdio.h> #include <stdlib.h> int *stog; int max = 0; int vrh = 0; int stavi(int element, int **stog, int *max, int *vrh){ if (*vrh < *max) (*stog)[(*vrh)++] = element; else { int *pom; pom = NULL; if ((pom = (int*)(malloc((*vrh) * sizeof(int)))) == NULL) return 0; for (int i=0; i < *vrh; i++) pom[i] = (*stog)[i]; free(*stog); *max = *max + 10; if ((*stog = (int *)(malloc(*max * sizeof(int)))) == NULL) return 0; for (int i=0; i < *vrh; i++) (*stog)[i] = pom[i]; free(pom); (*stog)[(*vrh)++] = element; return 1; int skini(int *element, int **stog, int *max, int *vrh){ if ((*stog == NULL) (*vrh == 0)) return 0; *element = (*stog)[--*vrh]; if (*max - *vrh > 19){ int *pom; pom = NULL; if ((pom = (int *)(malloc(*vrh * sizeof(int)))) == NULL) return 0; for (int i=0; i < *vrh; i++) pom[i] = (*stog)[i]; free(*stog); *max = *max - 10; if ((*stog = (int *)(malloc(*max * sizeof(int)))) == NULL) return 0; for (int i=0; i < *vrh; i++) (*stog)[i] = pom[i]; free(pom); return 1; 32

9. Napisati rekurzivnu funkciju koja će sadržaj jednostruko povezane liste prepisati u novu jednostruko povezanu listu na način da obrne poredak elemenata (prvi element u izvorišnoj listi postaje poslednji element u odredišnoj itd.). U postojeću jednostruko povezanu listu upisani su elementi tipa int. Funkcija mora vraćati 1 ukoliko je uspešno obavila posao, a 0 inače i imati prototip: int obrni(zapis **izvor, zapis **odrediste) #include <stdio.h> #include <stdlib.h> typedef struct elem { int broj; struct elem *sled; Elem; int obrni(elem **izvor, Elem **odrediste){ int k=0; Elem *m=(elem *)malloc (sizeof(elem)); if (*izvor){ m->broj=(*izvor)->broj; m->sled=(*izvor)->sled; else {m=null;k=1; if (m){ Elem *novi = (Elem *)malloc (sizeof(elem)); novi->broj = m->broj; novi->sled = *odrediste; *odrediste=novi; m=m->sled; k=obrni(&m,odrediste); return k; Elem *na_kraj (Elem *lst, int b) { if (!lst) { lst =(Elem *) malloc (sizeof(elem)); lst->broj = b; lst->sled = NULL; else lst->sled = na_kraj (lst->sled, b); return lst; void pisi (Elem *lst) { if (lst) { printf ("%d ", lst->broj); pisi (lst->sled); void main () { Elem *lst = NULL; int kraj = 0, izbor, broj, n,k;elem *lst1 = NULL; while (!kraj) { printf ("\n1. Dodavanje broja na kraj liste\n" "2. Ispisivanje liste\n" "3. Obrtanje i ispisivanje liste\n" "0. Zavrsetak rada\n\n" "Vas izbor? " ); scanf ("%d", &izbor); switch (izbor) { case 1: printf ("Broj? "); scanf ("%d", &broj); lst = na_kraj (lst, broj); break; 33

case 2: /* Ispisivanje liste: */ printf ("Lista= "); pisi (lst); putchar ('\n'); break; case 3: { k=obrni(&lst, &lst1); printf ("Lista= "); pisi (lst1); putchar ('\n'); printf(" %d\n",k); break; case 0: /* Zavrsetak rada: */ kraj = 1; break; default: /* Pogresan izbor: */ printf ("*** Neozvoljeni izbor! ***\a\n"); break; Napomene: Odredišna jednostruko povezana lista je na početku prazna. Izvorišna lista nakon izvršavanja funkcije treba ostati očuvana. 10. Napisati rekurzivnu funkciju koja će sadržaj dvostruko povezane liste prepisati u novu, jednostruko povezanu listu zadržavajući njihov poredak iz dvostruko povezane liste gledano od njene glave. U postojeću dvostruko povezanu listu upisani su elementi tipa int. Funkcija mora vraćati 1 ukoliko je uspešno obavila posao, a 0 inače i imati prototip: int prepisi(zapisj **glavajednostruka, zapisd **dvostrukaglava, zapisd **dvostrukarep) Napomene: Jednostruko povezana lista je prazna na početku. Početna dvostruko povezana lista nakon izvršavanja funkcije treba ostati očuvana. #include <stdio.h> #include <stdlib.h> typedef struct jedlist{ int broj; struct jedlist *sledeci; zapisj; typedef struct dvolist{ int broj; struct dvolist *sledeci; struct dvolist *prethodni; zapisd; int ucitaj(zapisd **dvostrukaglava,zapisd **dvostrukarep, int brel){ if(brel==0)return 1; *dvostrukaglava=(zapisd*)malloc(sizeof(zapisd)); *dvostrukarep=*dvostrukaglava; (**dvostrukaglava).sledeci=null; (**dvostrukaglava).prethodni=null; if(*dvostrukaglava==null)return 0; scanf("%d",&(**dvostrukaglava).broj); if(ucitaj(&(**dvostrukaglava).sledeci, dvostrukarep, brel-1)){ if((**dvostrukaglava).sledeci!=null)(*(**dvostrukaglava).sledeci).prethodni=(*dv ostrukaglava); return 1; 34

else return 0; int prepisi(zapisj **glavajednostruka, zapisd **dvostrukaglava, zapisd **dvostrukarep){ if(*dvostrukaglava==null) return 1; *glavajednostruka=(zapisj*)malloc(sizeof(zapisj)); if(*glavajednostruka==null)return 0; (**glavajednostruka).broj=(**dvostrukaglava).broj; (**glavajednostruka).sledeci=null; return(prepisi(&(**glavajednostruka).sledeci, &(**dvostrukaglava).sledeci, dvostrukarep)); void ispisi(zapisj *glavajednostruka){ if(glavajednostruka==null){ printf("\n"); return; printf("%d ",(*glavajednostruka).broj); ispisi((*glavajednostruka).sledeci); int main(){ int brel; zapisj *glavajednostruka; zapisd *dvostrukaglava,*dvostrukarep; printf("unesite broj elemenata dvostruko povezane liste:\n"); scanf("%d",&brel); printf("unesite redom sve elemente dvostruko povezane liste:\n"); if(ucitaj(&dvostrukaglava, &dvostrukarep, brel)==0){ printf("ne moze se obezbediti dovoljno memorije za izvrsenje zadatka. Prekid programa.\n"); return 1; if(prepisi(&glavajednostruka, &dvostrukaglava, &dvostrukarep)==0){ printf("ne moze se obezbediti dovoljno memorije za izvrsenje zadatka. Prekid programa.\n"); return 2; ispisi(glavajednostruka); return 0; 11. U jednostruko povezanu listu čuvaju se podaci o ispitima: matični broj studenta (long), šifra predmeta (int) i ocjena (short). Ocjena 0 označava da student nije pristupio ispitu (a prijavio ga je). Napisati funkciju koja će iz liste izbaciti sve zapise s ocjenom 0. Funkcija mora vratiti broj izbačenih zapisa i mora imati prototip: int izbaci(zapis **glava); 12. U dvostruko povezanu linearnu listu LIST smeštaju se podaci o procesima koji čekaju na izvršavanje: identifikator procesa (celi broj), prioritet procesa (celi broj), vlasnik procesa (polje znakova) i vreme pokretanja procesa (polje znakova). Lista je uređena prema prioritetu procesa (procesi sa najvećim prioritetom nalaze se na početku). Potrebno je napisati funkciju koja će zadanom procesu s identifikatorom idprocesa promeniti prioritet u prioritet i ponovno urediti listu prema prioritetu procesa. Funkcija treba imati prototip: void SetAndSort(LIST* lista, int idprocesa, int prioritet); #include<stdio.h> #include<stdlib.h> #include<string.h> 35

typedef struct listacv LIST; /*dvostruko povezana linearna lista*/ struct listacv{ int id; /*informaciono polje je clan niza x*/ int pr; char vl[30]; LIST *sledeci, *prethodni; ; LIST *lista, *kraj; LIST *ubaci(list *kraj, int id1, int pr1, char *vl1){ LIST *novi; /*novi cvor za umetanje u listu*/ novi=(list *)malloc(sizeof(list)); /*alokacija memorije za novi cvor liste*/ novi->id=id1; /*inicijalizacija polja u cvoru novi */ novi->pr = pr1; strcpy(novi->vl, vl1); novi->sledeci=null; novi->prethodni=kraj; /*novi element se dodaje na kraj postojece liste*/ kraj->sledeci=novi; /* do tada poslednji cvor kraj je ispred clana novi*/ kraj=novi; /*poslednji dodat element je novi kraj liste*/ return kraj; void Izbaci(LIST *el){ if (el->prethodni == NULL){ //Ako je el na pocetku liste onda stavljamo da je el->sledeci na pocetku liste lista = el->sledeci; lista->prethodni = NULL; return; if (el->sledeci == NULL){ //Ako je el na kraju liste onda stavljamo da je el- >prethodni na kraju liste kraj = el->prethodni; kraj->sledeci = NULL; return; LIST *pret, *sled; pret = el->prethodni; sled = el->sledeci; pret->sledeci = sled; //Ako je el bio u sredini liste onda stavimo da je sledbenik pret-a sled sled->prethodni = pret; return; void UbaciNaMesto (LIST *el){ LIST *trazi; trazi = lista; if (lista->pr < el->pr){ //Ako el ima veci prioritet od prvog cvora liste onda stavimo el->sledeci = lista; //el na pocetak liste el->prethodni = NULL; lista->prethodni = el; lista = el; return; if (kraj->pr > el->pr){ //Ako el ima manji prioritet od poslednjeg cvora liste onda stavimo el->prethodni = kraj; //el na kraj liste el->sledeci = NULL; 36

kraj->sledeci = el; kraj = el; return; trazi = lista->sledeci; while (trazi->pr > el->pr) //Pronadjemo prvi cvor liste koji nema prioritet veci od el-a i to je trazi trazi = trazi->sledeci; LIST *pret; pret = trazi->prethodni; //Postavimo el izmedju trazi->prethodnik i trazi pret->sledeci = el; el->prethodni = pret; el->sledeci = trazi; trazi->prethodni = el; return; void SetAndSort (LIST *lista, int idprocesa, int prioritet){ LIST *trazi; trazi = lista; while (trazi->id!= idprocesa){ //Pronadjemo cvor liste ciji id = idprocesa trazi = trazi->sledeci; Izbaci (trazi); trazi->pr = prioritet; UbaciNaMesto(trazi); //Iz liste izbacimo cvor koji smo nasli //promenimo mu prioritet //i ubacimo na odgovarajuce mesto u listi. int main(){ //LIST *kraj; int idu; int pru; char vlu[30]; int idprocesa, prioritet; FILE *ulaz; ulaz=fopen("procesi.txt", "r"); fscanf (ulaz, "%d%d", &idprocesa, &prioritet); fscanf(ulaz, "%d%d%s", &idu, &pru, vlu); lista=(list*)malloc(sizeof(list)); lista->id = idu; lista->pr = pru; strcpy(lista->vl, vlu); lista->sledeci = NULL; lista->prethodni = NULL; kraj = lista; while (!feof(ulaz)){ fscanf(ulaz, "%d%d%s", &idu, &pru, vlu); kraj=ubaci (kraj, idu, pru, vlu); //n++; fclose(ulaz); //Pretpostavimo da u listi sigurno postoji proces ciji je id = idprocesa 37