Język ANSI C część struktury rekurencyjne i ich zstosowni listy Jrosłw Grmcki Instytut Informtyki i Elektroniki struktury mogą zwierć w sobie definicje "rekurencyjne" czyli wskźniki do siebie smych dzięki tej włściwości możliwe jest tworzenie tkich złożonych struktur dnych jk listy lub drzew listy i drzew stosuje się w rzydkch gdy z góry nie widomo ile będzie trzeb rzechowywć dnych rzykłd: oliczyć ile rzy wystęuje kżde słowo w dnym liku tekstowym. Włściw struktur dnych: drzewo binrne szczegóły budowy konkretnej listy / drzew zleżą od jej zstosowni // list -kierunkow tyedef struct linked_list tyedef brdzo ułtwi zisy struct linked_list *next; // nstęn ozycj n liście chr nme[0]; // dne rzechowywne n liście int ge; // dne rzechowywne n liście LIST; // list -kierunkow tyedef struct double_list struct double_list *next; // w rzód struct double_list *rev; // w tył int ge; // dne rzechowywne n liście DLIST; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0)
// dodwnie elementów do listy -kierunkowej void dd_elem (chr *_nme, int _ge); LIST *dd_elem (LIST *, chr *_nme, int _ge); int dd_elem (LIST *, chr *_nme, int _ge); int dd_elem4 (LIST **, chr *_nme, int _ge); // różne oercje n liście -kierunkowej int find (LIST *, chr *_nme); int del_elem (LIST *, int _ge); void free_list (LIST *); void rintlist (LIST *); void rintdlist (DLIST *); void dotsk (LIST *, void (*fun) (int*, int) ); // wykonj fun() n elementch listy void elemfun (int *, int); // sortownie listy int comre (const void *, const void *); void sortlist (LIST *); // ostć wymgn rzez qsort() // z użyciem qsort() // dodwnie elementów do listy -kierunkowej void dd_delem (DLIST *, int _ge); UWAGA: w rzeczywistości rojekt owinien skłdć się n. z lików: list.h (rototyy, deklrcje struktur, zmienne globlne) list.c (definicje funkcji) min.c (rogrm główny) + "sterownie" cłością odowiednimi dyrektywmi rerocesor (#ifndef, #endif,...) dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) /* zmienn globln */ LIST *List = ; int min (void) dd_elem( "", 0 ); // 0 dd_elem( "", ); // 0... // dodwnie elementu n oczątek listy // List zmienn globln, źle!!! List void dd_elem (chr *_nme, int _ge) LIST *; = (LIST *) mlloc ( sizeof(list) ); // strcy ( ->nme, _nme); ->ge = _ge; ->next = List; // List = ; // 0 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 4
List 0 ierwszy element List kolejne elementy 0 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) /* zmienn globln */ LIST *List = ; int min (void) dd_elem( "", 0 ); dd_elem( "", ); rintlist(list); void rintlist ( LIST * ) while( ) rintf("(%s %d)", ->nme, ->ge)); = ->next; // dziłmy n koii // wskźnik rintf("\n"); 0 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 6
/* zmienn globln */ LIST *List = ; int min (void) dd_elem( "", 0 ); dd_elem( "", ); rintlist(list); // ierwsze wywołnie musi być z odstwieniem List =... // gdy strtujemy od ustej listy (w rzykłdzie oniżej nie jest to rwdą) // gdy list już istnieje, to odstwienie List =... jest zbędne List = dd_elem( List, "b", ); // 0 dd_elem( List, "b", 0 ); // 0 0 dd_elem( List, "b", ); // 0 0 rintlist( List); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) // dodwnie elementu n koniec listy LIST *dd_elem (LIST *, chr *_nme, int _ge) LIST *; LIST * = ; if ( == ) = (LIST *) mlloc ( sizeof(list) ); strcy ( ->nme, _nme); ->ge = _ge; ->next = ; // gdy ierwszy element bez List =... (trz orzedni sljd) dl kżdego wstwinego elementu wejdziemy tutj. Powód: funkcj NIE modyfikuje wrtości wskźnik else = (LIST *) mlloc ( sizeof(list) ); // strcy ( ->nme, _nme); ->ge = _ge; while( ->next ) // znjdz osttni element = ->next; // ->next = ; // ->next = ; // 4 ( rzyd się w del_elem()! ) // ->next = ; //, list cykliczn return ; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 8
0 b 4 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 9 /* zmienn globln */ LIST *List = ; int min (void) dd_elem( "", 0 ); dd_elem( "", ); rintlist(list); // ierwsze wywołnie musi być tkie gdy strtujemy od ustej listy // inczej list (z chociż jednym elementem) musi już istnieć // gdy list już istnieje, to odstwienie List =... jest zbędne List = dd_elem( List, "b", ); // 0 dd_elem( List, "b", 0 ); // 0 0 dd_elem( List, "b", ); // 0 0 rintlist( List); del_elem( List, 0 ); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 0
// ksuje dn z listy uorządkownej // nie mozn usunć ierwszego elementu // usuwny element musi znjdowć się n liście! źle z chwilę tką listę będziemy budowli int del_elem(list *, int _ge) LIST * = ; LIST *fter = ->next; // rzegldnie listy while( fter!= && fter->ge!= _ge) = ->next; // fter = fter->next; // ->next = fter->next; // tu błąd gdy ksownego elem. nie m n liście free(fter); // return (fter!= ); // czy sksowno cos? dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) del_elem( List, 0 ); fter 0 b del_elem( List, 0 ); fter 0 b? błąd ojwi się w tej linii: ->next = fter->next; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0)
/* zmienn globln */ LIST *List = ; // dodwnie elementu w sosób uorządkowny (wg. ol ge) // list musi już istnieć // m sens tylko dl listy uorządkownej // nie wstwi elementu mniejszego niż njmniejszy n liście // (gdyż nleżłoby zmodyfikowć korzeń, tu: ) // douszcz wstwinie duliktów int min (void) dd_elem( "", 0 ); dd_elem( "", ); rintlist(list); // ierwsze wywołnie musi być tkie gdy strtujemy od ustej listy // inczej list (z chociż jednym elementem) musi już istnieć // gdy list już istnieje, to odstwienie List =... jest zbędne List = dd_elem( List, "b", ); // 0 dd_elem( List, "b", 0 ); // 0 0 dd_elem( List, "b", ); // 0 0 rintlist( List); // del_elem( List, 0 ); dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 rintlist( List); efekt wstęnego nieuorządkowni listy dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) int dd_elem (LIST *, chr *_nme, int _ge) LIST *; LIST * = ; // rzeglądnie listy while(!= && (->ge < _ge)) = ; = ->next; // modyfikcj wskźnik OK, dziłmy n koii wskźnik //, // nowy węzeł = (LIST *) mlloc ( sizeof(list) ); //, 6 if ( == ) return FALSE; strcy ( ->nme, _nme); ->ge = _ge; // wstwienie nowego węzł do listy ->next = ; //, ->next = ; // 4, 8??? return TRUE; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 4
dd_elem( List, "c", ); c 0 b b 0 4 c dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) dd_elem( List, "c", - );, c 0 b b 0 8 c - "dzięki" temu ojwi się błąd rzy róbie drukowni listy (zętli się) 6 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 6
... dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 rintlist( List); del_elem( List, ); del_elem( List, ); rintlist( List ); // ksowny element musi być n liście dd_elem4( &List, "d", - ); dd_elem4( &List, "d", ); dd_elem4( &List, "d", - ); dd_elem4( &List, "d", 0 ); rintlist( List ); // dulikt // dodwnie elementu w sosób uorządkowny (wg. ol ge) // list musi już istnieć // m sens tylko dl listy uorządkownej // douszcz wstwinie duliktów // gdy wstwimy mniejszy element niż już jkikolwiek n liście // to modyfikuje korzeń (**) inny sosób to zwrócenie (zmodyfikownego) wskźnik z funkcji instrukcją return. Porównj z funkcją dd_elem() dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) int dd_elem4 (LIST **, chr *_nme, int _ge) LIST *; LIST *; LIST *fter; fter = *; = ; // wżny, trz niżej // rzeglądnie listy while( fter!= && (fter->ge < _ge)) = fter; fter = fter->next; // nowy wezel = (LIST *) mlloc ( sizeof(list) ); // if ( == ) return FALSE; strcy ( ->nme, _nme); ->ge = _ge; // wstwienie nowego wezl do listy ->next = fter; // if ( == ) // czy dołączyć n oczątek? * = ; // jeśli tk, to modyfikuj korzeń, // else ->next = ; // dołącznie nie n oczątek listy return TRUE; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 8
dd_elem4( &List, "d", - ); fter,... c - dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 9 // szuk nisu n liście int find(list *, chr *_nme) while (!= ) if ( strcm( ->nme, _nme ) == 0 ) brek; = ->next; return (!= ); void free_list(list *) LIST *; // konieczn zmienn omocnicz. Nie możn wykonć free() elementu // z którego dnych jeszcze chcemy skorzystć! while( ) = ; = ->next; free ( ); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 0
/* zmienn globln */ LIST *List = ; int min (void) dd_elem( "", 0 ); dd_elem( "", ); rintlist(list); // ierwsze wywołnie musi być tkie gdy strtujemy od ustej listy // inczej list (z chociż jednym elementem) musi już istnieć // gdy list już istnieje, to odstwienie List =... jest zbędne List = dd_elem( List, "b", ); // 0 dd_elem( List, "b", 0 ); // 0 0 dd_elem( List, "b", ); // 0 0 rintlist( List); // del_elem( List, 0 ); dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 rintlist( List); dotsk(list, elemfun); rintlist( List ); // elemfun - wskźnik do funkcji dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) // do kżdego elementu listy dodj + długość ol nme void dotsk (LIST *, void (*fun)(int*, int) ) for (; ; =->next ) fun ( &(->ge), strlen(->nme) ); // modyfikcj kżdego elementu listy // (*fun)( &(->ge), strlen(->nme) ); // lub tk void elemfun (int *, int b) * = * + b + ; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0)
... dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 dd_elem( List, "c", ); // 0 0 rintlist( List); del_elem( List, ); del_elem( List, ); rintlist( List ); // ksowny element musi być n liście dd_elem4( &List, "d", - ); dd_elem4( &List, "d", ); dd_elem4( &List, "d", - ); dd_elem4( &List, "d", 0 ); rintlist( List ); // dulikt rintf("comre: %d nd %d: %d\n", List->ge, List->next->ge, comre( List, List->next) ); rintf("comre: %d nd %d: %d\n", List->next->next->ge, List->ge, comre( List->next->next, List) ); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) // wersj odowiedni dl qsort() int comre ( const void *, const void * ) LIST *t = (LIST*); // OK LIST *t = (LIST*); // OK // dl: // LIST *t = ; // LIST *t = ; //"[Wrning] initiliztion discrds qulifiers from ointer trget tye" return ( (int*)(t->ge) - (int*)(t->ge) ); // źle (błąd komiltor) // "request for member `ge' in something not structure or union" int comre(const void *, const void *) return ( (int*)(list*)(->ge) - (int*)(list*)(->ge) ); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 4
DLIST firstdlist =,, - ; DLIST *DList = &firstdlist;... // ierwszy element dd_elem4( &List, "d", - ); dd_elem4( &List, "d", ); dd_elem4( &List, "d", - ); dd_elem4( &List, "d", 0 ); rintlist( List ); // dulikt rintf("comre: %d nd %d: %d\n", List->ge, List->next->ge, comre( List, List->next) ); rintf("comre: %d nd %d: %d\n", List->next->next->ge, List->ge, comre( List->next->next, List) ); dd_delem( DList, ); dd_delem( DList, ); rintdlist( DList ); // list -kierunkow tyedef struct double_list struct double_list *next; // w rzód struct double_list *rev; // w tył int ge; // dne rzechowywne n liście DLIST; dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) // wstwinie do listy -kierunkowej w sosób uorządkowny // list nie może być ust // nie wstwi duliktów void dd_delem (DLIST *, int _ge) DLIST *; DLIST *; // rzeglądnie listy while(!= && (->ge < _ge)) = ; = ->next; = (DLIST *) mlloc ( sizeof(dlist) ); ->ge = _ge; // ustw wskźniki if ( ) // obsług rzydku, gdy jeden element n liście ->rev = ; // ->next = ; // ->next = ; // ->rev = ; // 4 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 6
dd_delem( DList, ); dd_delem( DList, ); next - - rev 4 4 dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) void rintdlist ( DLIST * ) DLIST *tm; int count = 0; // od rzodu, korzystjąc z ol next while( ) tm = ; // tm odąż z rintf("%d ", ->ge); = ->next; count++; rintf("\n"); // od tyłu, korzystjąc z ol rev while ( count-- ) rintf("%d ", tm->ge); tm = tm->rev; rintf("\n\n"); dr inż. Jrosłw Grmcki, Instytut Informtyki i Elektroniki, UZ (ver..0) 8