Upload
ratko-ratko
View
214
Download
0
Embed Size (px)
Citation preview
8/20/2019 liste c
1/16
Programiranje 2 - 8
D. Vitas
Rekurzivne strukturepodataka
Olančavanje
Rekurzivne strukture podataka su strukture koje
sadrže pokazivač(e) na sebe samu. Ovakve
strukture omogućavaju niz proizvoljne dimenzije
(? - ograničen, ipak, veličinom memorije)
struct CELIJE {
int element;
struct celija * sledeci;
}
pokazivač na strukturu
Lista
Liste - osnovne definicije
Lista L je skup konačnih nizova elemanta istogtipa.
Neka je E = skup elemanta
E* = {(e1, e2, …, en) / n≥ 0, ei ∈ E za i = 1,…,n }• Dužina liste ((e1, e2, …, en)): |(e1, e2, …, en)| = n
• Prazna lista: ( ) =
• Pozicija ei u (e1, e2, …, en) = i
Elementu liste se pristupa SEKVENCIJALNO!
Osnovne operacije
Prazna_lista : Lista
Glava : Lista Adresa
Prvi : Lista Element
Nasl : Adresa Adresa
Rep : Lista Lista
Konstrukcija : Element x Lista Lista
(dodavanje elementa na (početak) liste)
Elem : Adresa Element
8/20/2019 liste c
2/16
Proširenja operacija
Dopisivanje
Proizvod : Lista x Lista Lista
(e1, …, en) . (f 1, …, f m) = (e1, …, en, f 1, …, f m)
Izmene
Dodavanje : Element x Adresa x Lista
Lista
dodati e posle elementa sa adresom p
Izbacivanje : Adresa x Lista
Lista
Element : Element x Lista
{T,F}
Ostalo
Mesto : Element x Lista Adresa
Pozicija : Element x Lista Ceo_broj
I_ti : Ceo_broj x Lista
Element
Sort : Lista
Lista
Moguće implementacije
nizdva niza
niz struktura
pokazivači (olančana lista)
Razlikuju se po načinu implementiranja operacija!
Olančana lista
Za razliku od niza kod koga je relacija sledeci
implicitno definisana, kod olančane liste je ova
relacija eksplicitno zadata. Svakom elementu
liste je dodata i informacija koja nam kazuje gde
se sledeći element nalazi, a koji ne mora biti u
neprekinutom nizu memorijskih lokacija.
Implementacija sa pokazivačima
L = (e1, e2, …, en)
KrajL
e1 e
2ei en
Adresa = memorijska adresa, eksplicitni naslednik
L se može poistovetiti sa Glava(L)
Prednosti: mnoge operacije su brže, jednostavno rukovanje,
pristup celoj dostupnoj memoriji, moguće je predstaviti niz bilo
koje dužine sa efikasnim operacijama dodavanja i brisanja
Nepognosti nema direktnog pristupa, troši brzo memorijuprimer38.c
NULL
Nizovi ili liste?
Prednosti nizova nad listama:
• Direktan pristup. Pristup i-tom članu niza ne
zavisi od i , dok je kod lista funkcija od i .
• Prostor . Kako je relacija sledeć i implicitnodefinisana, nije potreban dodatni prostor za
njeno kodiranje.
Prednosti lista nad nizovima:
• Sloboda u definisanju relacije sledeć i
• Zauzimanje prostora prema potrebi, dinamički.
Implementacija
... se u jezicima kakakv je C izvodi iz dva principa:
• elemente liste pozivamo preko njihovih adresa u
memoriji
• svakom elementu se dinamički dodeljuje prostor
u trenutku kada je to potrebno
Odavde slede sledeće deklaracije u C-u:
8/20/2019 liste c
3/16
Deklaracije
e
typedef structCELIJA { element elt;
struct CELIJA * sledeci ;} celija;
typedef celija * adresa;
typedef adresa lista; // Lista L= Glava(L)
a. Svaki element liste se fomira od n+1 polja (n polja za informacije u ćeliji
- tip element - i jedno polje za materijalizaciju relacije sledeći)
b. Poslednji element je obeležen tako što mu je sledeci NULL.
c. Listi se pristupa preko adrese prvog člana.
neki tip
Kreiranje liste
Definicija:
lista praznaLista(){return NULL; }
Poziv: lista L; ...;
L = praznaLista();
Efekat: lista L; ---> L = 0022FF48
.........................
L = praznaLista(); ---> L = 00000000
Unos u listu
Sa standardnog ulaza stižu karakteri koji predstavljaju
označene cele brojeve ili \n. Kraj ulaza je bilo koji drugi
karakter, npr. slovo a.
Formiramo novu listu L (tj. na početku L = NULL).
Lista se fomira tako da svaka ćelije sadrži, kao informaciju,
uneti broj... Sledeći broj se dodaje uvek na početak liste.
Npr. za unos brojeva 1, 2, 3, 4, 5, a, lista ima oblik
L = 5 4 3 2 1 (NULL)
Funkcija za unos
lista unosLista(){
int car; // Pročitani karakter
int x; // Čitanje broja
lista L, temp; // lista L i prvremena promenljiva temp
L = NULL; // Inicijalizacija L
while( 1 ) {
car = getchar(); // Čitanje karaktera...
if(!(isdigit(car)||(car=='+')||(car=='-')||(car=='\n'))) break;
if( isdigit(car)||(car=='+')||(car=='-')) {
ungetc(car, stdin); // Vraćanje u struju pročitanog car
scanf("%d", &x ); // Sada čitamo ceo broj
Funkcija za unos
temp = malloc( sizeof( celija ) ); // Alokacija
temp->element = x; // U polje element, x
temp->sledeci = L; // Sledeći = 1. u L
L = temp;} // Nova glava
} // Kraj while-petlje
return L; }
Primer
Unos liste 1 2 3 4 5 a
Deklaracija &L = 0022FF48 L = 0022FF48
Inicajlizacija L = 00000000Pre Posle
Unos 1 u listu L = 00000000 00580F28
Unos 2 u listu L = 00580F28 00580F90
Unos 3 u listu L = 00580F90 00580FA0
Unos 4 u listu L = 00580FA0 00580FB0
Unos 5 u listu L = 00580FB0 00580FC0
8/20/2019 liste c
4/16
Notacija
U funkciji unosLista bio je segment sa operatorom -->:
temp->element = x; // U polje element, x
temp->sledeci = L; // Sledeći = 1. u L
Alternativno (sa istim značenjem) može se koristiti
(*temp).element = x;
(*temp).sledeci = L; itd.
Ispis liste
void ispisLista( lista L ){
printf("LISTA: ");
for(; L; L = L->sledeci )
printf("%d ", L->element );
putchar('\n'); }
Za prethodni primer, rezultat poziva ove funkcije je:
LISTA: 5 4 3 2 1
Varijante
void ispisLista( lista L ){
lista p;
printf("LISTA: ");
p = L;
while( p != NULL) {
printf("%d ", p->element );
p = p->sledeci; }
putchar('\n');
}
Dodavanje i izbacivanje
Kod dodavanja novog elementa u listu imamo dvemogućnosti:
a. da dodamo novi element na početak liste (kao u funkcijiza unos)
b. da dodamo novi element na određenu poziciju u listi(npr. da tokom formiranja liste, sortiramo elemente)
Prednost pod a. – ne moramo obilaziti listu prilikom svakogdodavanja.
Slično za izbacivanje elementa iz liste.
Dodavanje na početak liste
Formirana je lista funkcijom unosLista
L = 4 3 2 1 NULL
Dodajemo x = 5 na početak liste:
a. Formiramo privremeni slog temp koji u poljuelement sadrži x = 5.
b. Sledeći element treba da bude početak liste L
c. Novi početak liste L je vrednost temp.
Dodavanje na početak liste
Na početak liste L dodajemo element x:
lista dodaj_na_pocetak( int x, lista L ){ // L = 4 3 2 1
lista temp = (lista) malloc( sizeof( celija ) );
temp->element = x; // temp->element = 5
temp->sledeci= L; // temp->sledeci je L
return temp; } // novi pocetak
8/20/2019 liste c
5/16
Izbacivanje sa početka
lista izbaci_sa_pocetka(lista L){lista temp = L->sledeci;
free( L );
return temp; }
Alternativno formiranje liste
int main() {
lista L;
/* Kreiranje liste L */
L = praznaLista();
L = dodaj_na_pocetak( 1 , L ); ispisLista( L );
L = dodaj_na_pocetak( 2 , L ); ispisLista( L );
L = dodaj_na_pocetak( 3 , L ); ispisLista( L );
L = dodaj_na_pocetak( 4 , L ); ispisLista( L );
return 0; }
Efekat: formirana lista 4 3 2 1
int main() {
lista L;
/* Kreiranje liste L */
L = praznaLista();
L = dodaj_na_pocetak( 1 , L ); ispisLista( L );
L = dodaj_na_pocetak( 2 , L ); ispisLista( L );
L = dodaj_na_pocetak( 3 , L ); ispisLista( L );
L = dodaj_na_pocetak( 4 , L ); ispisLista( L );
L = izbaci_sa_pocetka(L); ispisLista( L );
return 0; }
Efekat: izbačen poslednji uneti element u listu: 4 3 2 1
Dodavanje i izbacivanje
L
p
temp
L
p
temp
e
dodavanje temp *
izbacivanje temp *
Dodavanje
typedef struct CELIJA{ int element ;
struct CELIJA * sledeci ;} celija;
typedef celija * adresa ;
typedef adresa lista ;
.................................................................................lista dodaj ( lista L, adresa p, int e ) {
temp = (adresa) malloc( sizeof(celija) ) ;
if ( temp == NULL ) exit (1) ; // Prekoračenje heap-a
else { temp -> element = e ;
temp -> sledeci = p -> sledeci ;
p -> sledeci = temp ; }
return L ; }
Dodavanje i izbacivanje
L
p
temp
L
ptemp
e
dodavanje temp *
izbacivanje temp *
8/20/2019 liste c
6/16
Izbacivanje
... elementa posle ćelije sa adresom p:
/* bez oslobađanja memorije */p->sledeci = p->sledeci->sledeci;
/* sa oslobadjanjem memorije */
adresa temp;
temp = p->sledeci;
p->sledeci = temp->sledeci;
free(temp);
temp = NULL;
Pozicija
Funkcija vraća poziciju p prvog pojavljivanja
elementa x ako je u listi L, a ako nije, -1:
int pozicija( int x, lista L ) {
int p = 1;
for( ; L; L=L->sledeci, p++ )
if( x == L->element ) return p;
return -1; }
Prebrojavanje
Funkcija vraća broj pojavljivanja elementa x u listi
L.
int broj( int x, lista L ){
int c = 0;
for( ; L; L = L->sledeci )
if( x == L->element ) c++;
return c; }
Rekurzivno izbacivanje
lista izbacivanje( int x, lista L){
if( L ) {
if( x == L->element ) {
lista temp = L->sledeci;
free( L );
return izbacivanje( x, temp );
} else {
L->sledeci = izbacivanje( x, L->sledeci );
return L;
}
} else return L;
}
Oslobadjanje
void oslobadjanje( lista L ){
if( L ) {
lista temp = L->sledeci;
free( L );
oslobadjanje( L );
}
}
Podlista
Da li je lista L2 sadržana u listi L1?
typedef enum{FALSE, TRUE} boolean;
boolean podlista( lista L2, lista L1){
for( ; L2 && L1; L1 = L1->sledeci )
if( L2->element == L1->element ) L2 = L2->sledeci;
if( L2 == NULL ) return TRUE;
else return FALSE;
}
8/20/2019 liste c
7/16
Podlista (rekurzivno)
boolean podlistar ( lista L2, lista L1){
if( L2 == NULL )
return TRUE;
else if( L1 == NULL )
return FALSE;
else if( L2->element == L1->element )
return podlistar ( L2->sledeci, L1->sledeci);
else
return podlistar ( L2, L1->sledeci );
}
Da li je lista prazna?
boolean prazna( lista L ){
return L == NULL;
}
Implementiranje
Na početku časa su bile definisane operacije nad
listama, zatim smo razmatrali moguće
implementacije (nizovi i pokazivači), a onda smo
formirali jednu po jednu funkciju za rad sa
listama koje odgovarajudefinisanim
operacijama...
Kako u C-u organizovati rad sa listama?
1. korak - zaglavlje
Zaglavlje
typedef struct CELIJA {
int element;
struct CELIJA * sledeci;} celija;
typedef celija * p_celija;typedef p_celija lista;
typedef enum{FALSE, TRUE} boolean;
lista praznaLista();lista unosLista();
void ispisLista( lista );
boolean prazna(lista);
lista dodaj_na_pocetak(int, lista);lista izbaci_sa_pocetka(lista);
int pozicija( int, lista );int broj( int, lista);
void oslobadjanje( lista );
lista izbacivanje( int, lista);
boolean podlista( lista, lista);boolean podlistar( lista, lista);
2. korak – biblioteka funkcija
lista praznaLista() {...}
lista unosLista() {...}
void ispisLista( lista L) { ... }
boolean prazna(lista L) { ... }lista dodaj_na_pocetak(int x, lista L) { ... }
lista izbaci_sa_pocetka(lista L) { ... }
a onda formirati main()-funkciju koja eksploatišeove funkcije...
Na primer...
int main() {
lista L, L1;
boolean t;int p; /* pozicija elementa u listi */
/* Kreiranje liste L */
printf("Inicijalno L = %p \n", L);
L = praznaLista();
printf("Inicijalno L = %p \n", L);
/* Unos i ispis liste celih brojeva */
L = unosLista();
ispisL( L );/* Ispisuje listu ako nije prazna */
t = prazna( L );
if( !t ) ispisLista( L );/* dodavanje na pocetak liste */
8/20/2019 liste c
8/16
...
L = dodaj_na_pocetak( 5 , L );
ispisLista( L );
/* izbacivanje elementa sa pocetka liste */
L = izbaci_sa_pocetka( L );
ispisLista( L );
/* pozicija elementa x u listi L; -1 ako nije u listi */
printf("%d %d\n", pozicija( 2, L ), broj( 3, L ));
printf("%d %d\n", pozicija( 10, L ), broj(10, L));
/* Izbacivanje svih pojavljivanja elementa x iz liste L */
L = izbacivanje( 3, L);
ispisLista( L );
...
/* Unos i ispis podliste celih brojeva */
L1 = unosLista();
ispisLista( L1 );
/* ispitivanje da li je L1 podlista liste L */
t = podlista( L1, L);
if( t ) printf("Jeste\n");
else printf("Nije\n");
/* rekurzivno ispitivanje da li je L1 podlista liste L */
t = podlistar( L1, L);
if( t ) printf("Jeste\n");
else printf("Nije\n"); ... itd.
Stražar
Obilazak liste je frekventna operacija. Npr.
Obilazak liste da bi se utvrdilo da li se u listi
javlja vrednost x ima sledeću strukturu
while( p != NULL && p->element != x )
p = p->sledeci;
...
return p;
Stražar
Vrednost NULL može da bude i bilo koja druga,
unapred dogovorena vrednost adrese. Npr.
celija KrajSvihLista;
#define NULLBIS (&KrajSvihLista)
Stražar
Sada poslednji element liste pokazuje naNULLBIS:
NULLBIS->element = x;while( p->element != x )
p = p->sledeci;
...
return p;
Umesto dva poređenja imamo sada samo jedno!!!
Uređena lista
Uređena lista je lista čije ćelije imaju polje ključ koje
pripadaju nekom uređenom skupu vrednosti i za koje
važi:
Ako L->sledeci postoji, onda L->kljucsledeci->kljuc
Proces uređivanja podrazumeva sledeće korake:
1. pronaći mesto zanovi element
2. dodeliti prostror za novu ćeliju i popuniti joj polja
3. zakačiti tu ćeliju za listu “prelančavanjem”
8/20/2019 liste c
9/16
Sortiranje liste
/* Vraća pokazivač na ćeliju sa najmanjom vrednošću */
Celija * MINIMUM(Lista L) {Celija *minimum;
Celija *sled;
minimum=L;
sled=L;
while(sled!=NULL) {
if(sled->element < minimum->element) minimum=sled;
sled=sled->sledeci; }
return minimum;
}
Sortiranje - selekcija
Lista SELEKCIJA(Lista L) {
int tempo;
Celija *minimum;if( L == NULL ) return NULL;
minimum = MINIMUM( L );
if(minimum->elementelement) {
tempo = L->element;
L->element = minimum->element;
minimum->element = tempo; }
L->sledeci = SELEKCIJA( L->sledeci );
return L;
}
Varijacije u strukturi liste
- dvostruko olančane liste
- kružne liste
Skupovi
Apstraktni tip koji aproksimira konačne podskupove nekog
skupa E.
Osnovne operacije
Unija, presek, partitivni skup, …
PrazanSkup: Skup
Dodaj : Skup x Element Skup
Izbaci : Skup x Element Skup
Element : Skup x Element Bul
Prazan : Skup Bul
Skupovi
Implementacija
zavisi od tipa elementarnih operacija
Npr.
- niz bulovskih vektora
- uređeni niz
- olančana lista
Kasnije: heš-tablice i binarna drveta ...
Polinomi
[ ]⎭⎬⎫
⎩⎨⎧
∈≥= ∑=
n
i
i
i
i an xa X
0
,0/R
Skup
R
Operacije
zbir : Pol x Pol Pol
produit : Pol x Pol Polvrednost : Pol x FLOAT FLOAT, …
Aksiome
struktura prstena, …
Moguće implementacije
- preko nizova
- prekoolančanih lista
8/20/2019 liste c
10/16
Stek
Videli smo stek kao deo u organizaciji memorije.
Naziv dolazi od strukture podataka stek.
Stek je struktura podataka u kojoj se elementi
dodaju ili uklanjaju prema principu
" poslednji stigao, prvi opslužen"
(LIFO - Last In, First Out).
(Stek je podređen pojam za LIFO!)
Stek
e2
e3
en
e1
vrh-steka
e push(e, S)
epop(S)
Upravljanje stekom podrazumeva da se nećemo baviti time kako su
operatori implementirani već ćemo koristiti isključivo ove
primitivne operatore.
Primeri Stek
Osnovne operacije:
Konstrukcija : Φ --> Stek (pravi prazan stek)
Postavljanje_na_vrh: Stek x El --> Stek (push(e,S))
Skidanje_s_vrha : Stek --> Stek (pop(S))
Vrh_steka : Stek --> Element (peek(S))
Prazan_stek : Stek --> {T,F} (T ako prazan) (empty)
Pun_stek : Stek --> {T,F} (T ako je pun)
Isprazni_stek
Razori_stek
Stek
Uslovi pod kojima moraju biti definisane ove operacije:
• pop( S ) i peek( S ) su definisani ako je empty(S) = F
• pop( push( S, e )) = P• peek( push( S, e )) = e
• empty( Φ ) = T
• empty( push( S, e ) ) = F
Moguće implementacije
vrh
1 stek 2 steka > 2 steka
e2
en
e1Elt
Stek2
Stek1
olančane
liste
S1
S2
Stek se može implentirati preko niza ili preko
jednostruko olančane (povezane) liste.
8/20/2019 liste c
11/16
Implementacija preko niza
/* stek.h - zaglavlje za definiciju operacija na steku
* pomocu nizova */
typedef enum {N, T} boolean; //Logicki tip
int vrh( void ); // Vrh steka
void pop( void ); // Istiskivanje na stek
boolean push( int ); // Potiskivanje sa steka
boolean prazno( void ); // Testiranje da li je stej prazan
void ispis_steka( void ); // Ispisvanje sadrzaja steka
stek.h
Implementacija preko niza
/* stek.c - definisanje operacija nad stekom (implementacija preko nizova) */#include
#include "stek.h"
#define Duzina 20 //Duzina steka
static int stek[ Duzina ]; // Stekstatic int index_vrha = -1; // Prazan stek
void pop( void ) { // Istiskivanje sa steka
if( index_vrha == -1 ) printf(" Prazan stek\n");
else index_vrha--; }
boolean push( int x ) { // Potiskivanje na stek
if( index_vrha == Duzina - 1 ){ //Ima li slobodnih pozicija?
printf(" Stek popunjen\n");
return N;}
else { stek[ ++index_vrha ] = x;
return T; } }stek.c
Implementacija preko niza
boolean prazno( void ) {return index_vrha = -1; }
void ispis_steka( void ) { // Ispisivanje steka
int i;
printf(" STEK: ");for( i = 0; i
8/20/2019 liste c
12/16
vrh (peek)
Pristup vrhu
Vrh steka je poslednji dodati element. Funkcijavraća 1 u slučaju prazne liste, a 0 inače.
int Vrh( Stek P, TipPodataka *pelem) {
if( PrazanStek( P ) ) return 1;
*pelem = P->podatak; // vracamo vrh steka
return 0; }
Dodavanje na vrh steka
void push( Stek *pP, TipPodataka elem ) {
Stek q;
q = (TipCelija *)malloc(sizeof( TipCelija)); //Alokacija
q->podatak = elem;
q->sledeci = *pP; // umetanje na pocetak liste
*pP = q; //Azuriranje glave liste }
Skidanje sa steka
void pop( Stek *pP, TipPodataka *pelem) {
Stek q;
if( PrazanStek ( *pP ) ) return 1; // nema pop-a
*pelem = (*pP)->podatak; // pamtimo prvi element liste
q = *pP; // pamtimo adresu prve celije
*pP = (*pP)->sledeci; // prelazak na element ispod vrha
free( q ); // oslobadjanje prostora koji je zauzimao vrh
return 0; }
Pražnjenje i razaranje steka
void Razaranje( Stek *pP ) {
Stek q;
while( *pP != NULL ) { // Obilazak liste
q = *pP;
*pP = (*pP)->sledeci;
free( q ); }
*pP = NULL; // prazna lista }
void Isprazni( Stek *pP ) {
Razaranje( pP );
*pP = NULL; }
Primer 1.
Izračunavanje aritmetičkog izraza u prefiksnomobliku... Neka izraz obrazuju celi neoznačenibrojevi i operatori +, * i ( )
Izraz u prefiksnom obliku je ili pririrodan broj iliizraz oblika (+ e1 e2) ili (* e1 e2)
Primer. 1. 55 je izraz
2. (+ (* 2 3 ) (+ 12 8 )) je izraz
čija je vrednost 26
Primer 1.
Na stek potiskujemo samo operatore i prvi argument, a opearciju izvršavamokada naiđe drugi argument (zagrade nisu potrebne).
(+ (* 2 3 ) (+ 12 8 )) = + * 2 3 + 12 8
Operacije Sadržaj steka
push(+) +
push(*) + *push(2) + * 2
stiže 3, skinuti 2 * vrh i
izvršiti operaciju *,
rezultat na stek + 6
+ 6 +
+ 6 + 12
+ 6 20
26
8/20/2019 liste c
13/16
Primer 2. Hanojske kule
H (n, x, y, z) =x-y si n = 1
H (n-1, x, z, y) . x-y . H (n-1, z, y, x) si n > 1
a b c
Iterativni zapis
H( n, x, y, z ) {
StekP y' ");
else { /* e = ( n, x', y', z' ) */
push( P, ( n-1, z', y', x' ) );
push( P, x' --> y' );
push( P, (n-1, x', z', y' ) )
}
}
}
H(3,a,b,c)
H( n, x, y, z ) {StekP y' ");else { /* e = ( n, x', y', z' ) */
push( P, ( n-1, z', y', x' ) );
push( P, x' --> y' );push( P, (n-1, x', z', y' ) )
}
}}
(3,a,b,c)e b
(2,a,c,b)
----------------------------e b
(1,b,c,a)
c--> b(1,a,b,c)
---------------------------
e a --> b itd.
Primer 3.
Data je lista L celih brojeva. Ispisati je u obrnutom
redosledu.
Npr. L = ( 1 2 3 4 5). Treba ispisati 5 4 3 2 1.
Pristup samo preko glave liste...
Rešenja
1. stek (ili rekurzivna funkcija) R1
2. prelančavanje R2
3. n prolazaka kroz listu R3
nemaconst.n2R3
imaconst.nR2
nemannR1
ModifikacijaProstorVreme
Red (queue)
... ili red čekanja je struktura na principu FIFO
(First In, First Out).
U ovoj strukturi podataka, elementi se dodaju s jednog kraja, a uzimaju s drugog...
8/20/2019 liste c
14/16
Redovi Redovi
Ulazak u red: put (enqueue, push, insert, in, dodaj,...)
Izlazak iz reda: get (dequeue, pop, remove,out, skini,...)
Redovi
Konstrukcija : Φ --> Red (pravi prazan red)
Postavljanje_u_redh: Red x El --> Red (push(e,R))
Skidanje_iz_reda : Red --> Red (pop(R))
Prvi_u_redu : Red --> Element
Prazan_red : Red --> {T,F} (T ako prazan) (empty)
Pun_red : Red --> {T,F} (T ako je pun)
Isprazni_red
Razori_red
Uslovi
• Skini(R) i Prvi(R) su definisane ako je
Prazan(R)=F
• Prazan(R)=T ==> Prvi(Dodaj(R,e)) = e
• Prazan(R)=F ==> Prvi(Skini(R,e))=Prvi(R)
• Prazan(R)=F ==>
Skini(Dodaj(R,e))=Dodaj(Skini(R,e))
• Prazan(Dodaj(R,e)) = F
...
Implementacija
Moguće implementacije:
1. preko niza sa dva indeksa (početak i kraj reda)
en
ei
ei+1
e1
MAX -1
01
2Red
Prvi
Sledeći( i ) = (i + 1)%MAX
Uslov:
MAX ≥ max | F | + 1F
Implementacije
2. preko kružne liste
e1 en-1en
F = (e1, e2, …, en)
8/20/2019 liste c
15/16
o e1 oo e2 o en-1 o
oF dodavanjee
en-1oooo e e1 e2
oF
Fkonstantno vreme
o
en-1 ooooooen e e1 e2
Primena
bafer (buffer ) – programska konstrukcija za
privremenočuvanje podataka, npr. tastatura ilipodaci sa diska...
Promenljivi broj argumenata
...
Funkcija u C-u ne mora da ima fiksiran brojargumenata. Npr,
gde lista može da sadrži različit broj argumenata.
Slično, umesto
max(a,b) --> max(a,b,c,d,e)
strcat(a,b) --> dopis(a,b,c,d,e,f)
printf(format, lista);
...
Ovkava mehanizam je moguć u C-u pod uslovom
da je ili poznat broj argumenata (kod printf –
broj argumenata se određuje iz formata) ili da je
na određeni način obeležen kraj listeargumenata.
Npr. za dopis – dve mogućnosti:
dopis(“dobar”,”dan”,”deco”,NULL)
dopis(3, “dobar”,”dan”,”deco”)
Deklaracije
U deklaraciji funkcije mora biti naveden
• barem prvi argument
• ostali se deklarišu sa ...
Npr.
char *dopis(char *,...);
int max(int nargs,...);
8/20/2019 liste c
16/16
Definicija
Definisanje je omogućeno preko kojasadrži konstrukcije za rad sa promenljivimbrojem argumenata.
va_list args: deklariše promenljivu args tipa void *
va-start(args,nargs): inicijalizuje args kao adresuargumenta koji sledi iza nargs (args = &nargs+1)
va_arg(args,int): vraća vrednost tekućegargumenta (tipa int) i napreduje na sledećielement
va_end(args): restaurira početno stanje liste
Primer 1.
/* primer60.c - funkcija zbir sa promenljivim brojem argumenata */
#include
#include
int zbir( int, ... );
main(){
printf("%d\n", zbir(3, 1, 2, 3) ); // zbir = 6
}
int zbir( int nargs, ...) {
va_list args; // deklaracija
int i, s = 0;
va_start( args, nargs); // inicijalizacija
for( i = 0; i < nargs; i++ )
s += va_arg( args, int ); // sabiranje
va_end( args ); // brisanje
return s;
}
Primer 2.
/* primer61.c - funkcija za odredjivanje maksimuma brojeva (prvi parametar je broj brojeva koji seporede) */
#include
#include // dostupnosy INT_MIN
#include
int max( int, ... );
main() {
printf("%d\n", max(7, 1, 2, 3, 4, 5, 6, 7) );
printf("%d\n", max(3, -1, -2, -3) );
}
int max( int nargs, ... ) {
va_list args;
int i, x, maxl = INT_MIN; // maxl - maksimalna vrednost
va_start( args, nargs );
for( i = 0; i < nargs; i++ )
if( (x = va_arg( args, int )) > maxl ) maxl = x;
va_end( args );
return maxl;
}
Primer 3.
/* primer62.c - dopisivanje vise niski */#include
#include
#include char *dopis(char *, ...);
main(){
printf("%s\n", dopis("Dobar ", "dan",","" narode","!", NULL) ); }
char *dopis(char *rec, ...) {va_list niske;
char *x, *gde, *r;
int l; /* 1. prolaz – određivanje dužine rezultujuće niske */
l = strlen(rec);
va_start( niske, rec );while( x = va_arg( niske, char *) ) // Poslednji argument je NULL !!!
l += strlen(x);
va_end( niske ); // Restauracija
Primer 2. (cont.)
/* 2. prolaz – alociranje prostora i dopisivanje */
gde = (char *) malloc( l + 1 ); // Alokacija
strcpy( gde, rec);
gde += strlen( rec );
va_start( niske, rec ); // Inicijalizacija
while( x = va_arg( niske, char * ) ) {
strcpy( gde, x );
gde += strlen( x );
}
va_end( niske ); // Restauracija
return r;
}