liste c

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;

    }