Documente online.
Zona de administrare documente. Fisierele tale
Am uitat parola x Creaza cont nou
 HomeExploreaza
upload
Upload




Tipul abstract "Lista". Liste stiva.

Informatica


5. Tipul abstract "Listă". Liste stivă.

Liste (secvente) de date



Tipul abstract "Listă" are mai multe definitii posibile:

- O colectie liniară de elemente, în care fiecare element este accesibil printr-un indice întreg, care arată pozitia elementului respectiv în listă.

- O secventă de elemente, în care fiecare element are un succesor si, eventual, un predecesor.

Lista nu este o structură de căutare ci doar o structură pentru memorarea temporară a unor date.

Diferentele principale între o listă si o multime sunt:

- Intr-o listă pot fi mai multe elemente egale.

- Intr-o listă nu se fac căutări frecvente după valoarea (continutul) unui element.

Operatiile cu tipul abstract "Listă" pot fi grupate în:

- Operatii comune oricărei colectii : initializare (initL), determinare dimensiune (sizeL), adăugare la sfârsit de listă (addL) s.a.

- Operatii specifice clasei abstracte "List" : citire (getL), modificare (setL), inserare (insL), stergere (removeL), toate într-o pozitie dată (un indice întreg).

Functiile de acces pozitional au rezultat 0 ('fals') dacă indicele "pos" este în afara listei si rezultat 1 ('true') dacă operatia a reus 16416i87q it. Indicele este o variabilă a programului de aplicatie, deci un cursor extern listei. Pot fi mai multe variabile cursor, cu valori diferite, pe o aceeasi listă.

Pentru a realiza operatiile de acces secvential ("first" si "next") se foloseste un cursor intern, deci o variabilă suplimentară de tip întreg sau pointer, functie de implementarea listei.

Implementările principale pentru tipul abstract "Lista" sunt două: vector si listă înlăntuită.

Un vector este recomandat pentru liste cu continut stabil, atunci când este necesar un acces aleator frecvent la elementele listei, ca în operatiile de sortare sau de căutare binară.

O listă înlăntuită se recomandă atunci când dimensiunea listei este greu de estimat, fiind posibile multe adăugări si/sau stergeri din listă, sau atunci când sunt necesare inserări de elemente în interiorul listei. Desi este posibil accesul pozitional, printr-un indice întreg, la elementele unei liste înlăntuite, utilizarea sa frecventă afectează negativ performantele aplicatiei.

Exemple de functii pentru operatii cu o listă abstractă realizată ca listă simplu înlăntuită.

typedef int T ; // tip date aplicatie

typedef struct sn Nod, * Pnod, *List;

// initializare lista

List initL ()

// adaugare la sfarsitul listei

void addL (List lst, T x)

// acces pozitional, pe baza de indice

T getL (List lst, int i)

return p->val;

// dimensiune lista

int sizeL (List lst)

// introducere in lista in pozitia i

void insL (List lst, int i, T x)

n->leg=p; q->leg=n;

// afisare lista, cu acces pozitional

void pprintL (List lst)

printf ("\n");

// creare si afisare lista

void main ()

Căutarea binară, într-o listă ordonată, necesită acces pe bază de indice, la elementul median din listă, dar nu se justifică decât pentru liste implementate prin vectori.

Ca exemplu de prelucrare simplă a unei liste si care necesită accesul aleator (prin indice) la elementele listei vom prezenta o functie care "amestecă" elementele unei liste (operatie inversă ordonării, similară amestecării unui pachet de cărti de joc). Functia "setL" modifică (înlocuieste) valoarea dintr-o pozitie dată a unei liste si este aproape la fel cu functia "getL".

// schimba intre ele valorile din pozitiile i si j

void swap ( List lst, int i, int j)

// amesteca elementele listei

void shuffle (List lst)

void main ()

Liste stivă

O stivă este o listă cu acces la un singur capăt, numit "vârful" stivei. Singurele operatii permise sunt introducere în prima pozitie si extragere din prima pozitie (eventual si citire din prima pozitie). Aceste operatii sunt denumite traditional "push" (pune pe stivă) si "pop" (scoate din stivă) si nu mai specifică pozitia din listă, care este implicită . O stivă mai este numită si listă LIFO ('Last In First Out'), deoarece ultimul element pus este primul care va fi extras din stivă.

Operatiile cu o stivă pot fi privite ca niste cazuri particulare de operatii cu liste oarecare:

// pune x pe stiva

void push ( List lst, T x)

// scoate din stiva in x

T pop ( List lst )

De obicei stiva este abordată direct ca un vector sau ca o listă înlăntuită. Urmează functii pentru operatii cu o stivă realizată ca un vector extensibil, cu adăugare si stergere la sfârsitul vectorului.

#define INC 100 // increment extindere stiva

typedef int T; // tip date puse pe stiva

typedef struct st stiva, *Stack;

// initializare stiva

Stack initS ()

// pune pe stiva o valoare x

void push (Stack s, T x)

s->st [s->sp++]=x;

// scoate valoarea din varful stivei

T (Stack s)

// test stiva goala

int emptyS (Stack s)

Stiva listă înlăntuită, cu adăugare si extragere numai la începutul listei, poate fi o listă cu santinelă. Exemplu de functii pentru operatii cu o stivă listă fără santinelă:

typedef struct s Nod, * stack ;

typedef stack* Stack;

// initializare stiva

Stack initSt ()

// test stiva goala

int emptySt (Stack s)

// pune in stiva un element

void push (Stack s, T x)

// scoate din stiva primul element

T pop (Stack s)

Principalele utilizări pentru o stivă sunt:

- Eliminarea recursivitătii, prin memorarea temporară a unor date (si adrese);

- Inversarea ordinii unui sir de valori (prelucrare în ordine inversă adăugării).

Exemplul următor poate fi privit ca utilizare a stivei pentru afisarea în ordine inversă a resturilor împărtirii prin 2, dar si ca utilizare a stivei pentru eliminarea recursivitătii la conversia în binar.

// afisare numar in binar (nerecursiv)

void binar (int n)

while (! emptySt(st))

// afisare in binar (recursiv)

void binar (int n)

Utilizare stivă pentru eliminarea recursivitătii directe

Functiile recursive cu mai multe apeluri recursive sau cu un singur apel care nu este si ultima instructiune din functie nu pot fi rescrise iterativ fără a utiliza o stivă.

De exemplu, functia nerecursivă pentru afisarea valorilor dintr-un arbore binar foloseste o stivă pentru a memora adresele nodurilor prin care s-a trecut dar care nu au fost afisate, urmând ca la revenirea prin aceste noduri să se afiseze valorile lor. Pentru ca stiva să nu se golească complet se pune initial în stivă o adresă oarecare (diferită de NULL):

// afisare infixata nerecursiva arbore binar

void infix (Nod * r)

else

}

} while ( r!= x));

printf ("\n");

Evolutia stivei 'st' la afisarea infixată a arborelui binar

5 (2 (1,4) , 8 (6,9) )

Oper. Stiva Afisare

push(x) x

push (&5) x,&5

push (&2) x,&5,&2

push (&1) x,&5,&2,&1

pop x,&5,&2 1

pop x,&5 2

push(&4) x,&5,&4

pop x,&5 4

pop x 5

push (&8) x,&8

push (&6) x,&8,&6

pop x, &8 6

pop x 8

push (&9) x,&9

pop x 9

Utilizare stivă pentru trecere la forma postfixată

Intr-o expresie aritmetică ordinea de calcul (de aplicare a operatorilor aritmetici) este în general diferită de ordinea în care operatorii apar în expresie. Exemplu de expresie cu paranteze:

a + (b-c) / (d+e)

Ordinea de evaluare a subexpresiilor este următoarea:

t1=b-c; t2=d+e; t3=t1/t2; t4=a+t3;

Expresiile în care un operator binar apare între cei doi operanzi se numesc si expresii infixate. S-a propus si o altă formă de scriere a expresiilor aritmetice, care nu foloseste paranteze si care tine seama de prioritatea operatorilor- forma postfixată, în care fiecare operator apare după operanzi. Expresia anterioară, în forma postfixată, arată astfel:

abc-de+/+

Trecerea de la forma infixată la forma postfixată a expresiilor aritmetice foloseste o stivă de operatori. Operanzii din sirul infixat sunt trecuti direct în sirul postfixat, iar operatorii trec prin stivă, de unde se scot în functie de rezultatul comparatiei prioritătii operatorului extras din sirul infixat cu prioritatea operatorului din vârful stivei. Algoritmul poate fi descris astfel:

repeta pana la terminarea sirului infixat

extrage urmatorul caracter din sir in ch

daca ch este operand atunci trece ch in sirul postfixat

daca ch este "(" atunci se pune ch in stiva

daca ch este ")" atunci

extrage din stiva pana la "(" (inclusiv) si trece in sirul postfixat

daca ch este operator atunci

repeta cat timp prior(ch) < prior(operator din varful stivei)

scoate din stiva in sirul postfixat

pune ch in stiva

scoate tot ce a ramas in stiva si adauga la sirul postfixat

afiseaza sir postfixat

Program pentru expresii cu operanzi de o singură cifră si cu patru operatori binari si paranteze:

// determina prioritate operator

int pri (char op) ;  // tabel operatori

int pr[] =;

for (k=0;k<nop;k++)

if (op==top[k])

return pr[k];

return -1;

// trecere expresii aritmetice la forma postfixata

void main ()

} while (! empty(st));

// afisare sir postfixat

*b=0; // ptr o afisare mai simpla

printf("%s\n",out);

Initial stiva de operatori trebuie să contină un operator de prioritate mică, pentru prima comparatie cu operatorul (paranteza) din sirul infixat. O solutie este adăugarea de paranteze în jurul expresiei initiale, iar o altă solutie este folosirea operatorului de atribuire (prezent în instructiunile aritmetice de atribuire).

Evaluarea unei expresii postfixate se face prin parcurgere de la stânga la dreapta, folosind o stivă pentru operanzi si rezultate intermediare: la întâlnirea unui operator în sirul postfixat se scot cei doi operanzi din vârful stivei, se aplică operatorul si se pune rezultatul operatiei pe stivă.


Document Info


Accesari: 3194
Apreciat: hand-up

Comenteaza documentul:

Nu esti inregistrat
Trebuie sa fii utilizator inregistrat pentru a putea comenta


Creaza cont nou

A fost util?

Daca documentul a fost util si crezi ca merita
sa adaugi un link catre el la tine in site


in pagina web a site-ului tau.




eCoduri.com - coduri postale, contabile, CAEN sau bancare

Politica de confidentialitate | Termenii si conditii de utilizare




Copyright © Contact (SCRIGROUP Int. 2024 )