WYKŁAD 10 Zmienne o złożonej budowie Statyczne i dynamiczne struktury danych: lista, kolejka, stos, drzewo Programy: c5_1.c, c5_2, c5_3, c5_4, c5_5 Tomasz Zieliński ZMIENNE O ZŁOŻONEJ BUDOWIE (1) Zmienne typu prostego: char, short, int, long, float, double (unsigned) char, short, int, long Przykład: char c, s[10]; int i, j, k, l, m[3][3], n[5][5][5]; float x, y, z c = getchar(); strcpy(s, ”Kowalski”); i = 10; j = 20; k = i+j; l = i*j; m[0][1] = 1; n[0][1][2] = m[1][2] + 128; ZMIENNE O ZŁOŻONEJ BUDOWIE (2) Zmienne typu złożonego (struktury) Przykład: struct osoba { <--------------- typ zmiennych osoba char nazwisko[20]; char imie[10]; int wiek; int wzrost; } student; <--------------- delaracja zmiennej student typu osoba strcpy( student.nazwisko, ”Kowalski” ); strcpy( student.imię, ”Jan” ); student.wiek = 23; student.wzrost = 187; // inicjalizacja zmiennej // // // struct osoba pacjent, student = {”Kowalski”, ”Jan”, 23, 187}; ZMIENNE O ZŁOŻONEJ BUDOWIE (3) Przykład: struct osoba { <---------- typ zmiennych osoba char nazwisko[20]; char imie[10]; int wiek; int wzrost; } *pstudent; <--------- delaracja wskaźnika do zmiennej student ZASADA ZAPISU: *xxx.yyy = xxx->yyy strcpy( pstudent->nazwisko, ”Kowalski” ); // inicjalizacja zmiennej strcpy( pstudent->imię, ”Jan” ); // inicjalizacja zmiennej pstudent->wiek = 23; pstudent->wzrost = 187; struct osoba *ppacjent, *pstudent = {”Kowalski”, ”Jan”, 23, 187}; STRUKTURY DANYCH (1) - statyczne i dynamiczne Lista: Kolejka: Stos: Drzewo: Statycznie: użytkowników komputera, uczestników wycieczki, studentów, pacjentów, ... dokumentów czekających na wydrukowanie przez drukarkę sieciową danych o przerwanych (zawieszonych) programach, czekających na wykonanie przez procesor katalogów zbiorów na dysku komputera tablica, składająca się z wielu elementów jednego typu, często nie w pełni wypełniona, czasami przepełniona Dynamicznie: łańcuch węzłów (bloków komórek w pamięci), które na siebie pokazują STRUKTURY DANYCH (2) - statyczne i dynamiczne Kolejka statycznie A B początek I J K L C D Kolejka dynamicznie wezeł nr 1 komórki pamięci E koniec A F G wezeł nr 2 komórki pamięci adr adr C adr H początek koniec B wezeł nr 3 komórki pamięci adres pierwszego węzła początek struct kolejka { int początek; int koniec; struct osoba tablica[ MAX ]; } | | | | | | | | koniec adres ostatniego węzła struct kolejka { int początek; int koniec; } struct węzeł { struct osoba student; struct węzeł *następny; } DYNAMICZNE STRUKTURY DANYCH (1) Węzły ===================================================== struct węzeł1 { struct węzeł2 { struct element info; struct element info; struct węzeł1 *następny; struct węzeł2 *poprzedni; }; struct węzeł2 *następny; }; ===================================================== Przykład: struct element { // w każdym węźle jest umieszczona int liczba; // jedna liczba, np. 220 char litera; // i jedna litera, np. V (voltów) }; Dynamiczna alokacja pamięci dla węzła i jej zwalnianie: pwęzeł = (struct węzeł *) malloc( sizeof( struct węzeł ) ); free( pwęzeł ); DYNAMICZNE STRUKTURY DANYCH (2) Lista jednostronna info A adr info B adr adr info B adr info X adr info Y początek info A info C początek info A początek info X adr info B adr adr info Y DODAWANIE adr info X adr info Y USUWANIE DYNAMICZNE STRUKTURY DANYCH (3) Lista dwustronna info A adr adr info B adr adr info X adr adr info Y info B adr adr info X adr adr info Y info B adr adr wskaźnik adr info A adr adr adr wskaźnik info B adr adr adr info C adr info X adr DODAWANIE info A adr adr USUWANIE info X adr DYNAMICZNE STRUKTURY DANYCH (4) Kolejka FIFO (First In First Out) w statycznym buforze kołowym A B C D początek A B E koniec C D E początek A I J B F koniec C D E F początek koniec L F K koniec G początek H DYNAMICZNE STRUKTURY DANYCH (5) Kolejka FIFO (First In First Out) dynamicznie A adr B adr początek A C adr koniec adr B adr C adr początek A D adr koniec adr B początek adr C adr D koniec adr DYNAMICZNE STRUKTURY DANYCH (6) STOS statycznie i dynamicznie Statyczna tablica A B C D Dynamiczna struktura E C B C D E F ostatni A B C D ostatni B adr A adr ostatni ostatni A adr D adr C adr B adr A adr adr C adr B adr A adr ostatni D ostatni DYNAMICZNE STRUKTURY DANYCH (7) - drzewo binarne A 14 adr L adr P B C 9 adr L adr P adr L D 21 E 5 16 F 30 adr L adr P adr P G 6 H 15 WYPISYWANIE ELEMENTÓW: IN-ORDER lewo, wypisz, prawo I 20 5, 6, 9, 14, 15, 16, 20, 21, 30 D, G, B, A, H, E, I, C, F -------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------- PRE-ORDER POST-ORDER wypisz, lewo, prawo lewo, prawo, wypisz A, B, D, G, C, E, H, I, F G, D, B, H, I, E, F, C, A DYNAMICZNE STRUKTURY DANYCH (8) - drzewo binarne Poprzednia strona: struct węzeł { struct element struct węzeł struct węzeł }; info; *lewy; *prawy; np. ------> struct element { char litera; int liczba; } Przykład: + A A + (B - C) * (D + E) * - B + C D E /* Przyklad 5.5 - DRZEWO BINARNE - jako struktura dynamiczna /* wprowadzaj liczby naturalne z klawiatury /* znajdz szybko pierwsze powtorzenie /* wydrukuj od najmniejszej do najwiekszej */ */ */ */ #include <stdio.h> #include <conio.h> #include <stdlib.h> struct wezel { int struct wezel struct wezel }; /* struktura wezla */ info; *lewy; *prawy; typedef struct wezel *ADRwezel; ADRwezel PobierzWezel( void ); /* deklaracja adresu do wezla */ /* pobranie wolnego wezla */ ADRwezel NowaGałąź( int x ); void PoLewej( ADRwezel p, int x); void PoPrawej( ADRwezel p, int x); /* wygeneruj kolejna galaz */ /* wstaw liczbe x do lewej galezi */ /* wstaw liczbe x do prawej galezi */ void Preorder( ADRwezel p ); void Inorder( ADRwezel p ); void Postorder( ADRwezel p ); /* kolejnosc 1 */ /* kolejnosc 2 */ /* kolejnosc 3 */ /* program glowny ---------------------------------------------------------------------- */ void main() { int liczba; ADRwezel ADRwezel pdrzewo; p, q; printf( "\n Podawaj liczby naturalne. Koniec = jakas litera ! \n\n "); scanf( "%d", &liczba ); pdrzewo = NowaGałąź( liczba ); /* podaj pierwsza liczbe */ /* bedzie ona korzeniem drzewa */ while ( scanf("%d", &liczba ) != NULL ) // wczytuj kolejne liczby { p = q = pdrzewo; while( liczba != p->info && q != NULL ) // powtarzaj kiedy rozne { // 1. rozne liczby p = q; // 2. drzewo jest nizej if ( liczba < p->info ) q = p->lewy; // jesli mniejsze, to w lewo else q = p->prawy; // jesli wieksze, to w prawo } if ( liczba == p->info ) // znaleziono podana liczbe/ printf(" Liczba %d zostala juz wczytana !\n", liczba ); else if ( liczba < p->info ) // koniec galezi drzewa PoLewej( p, liczba ); // wstaw liczbe do lewej odnogi else PoPrawej( p, liczba); // wstaw liczbe do prawej odnogi } printf("\n Inorder :\n"); Inorder( pdrzewo ); // Rozne sposowy wyszukiwania // elementow w drzwie binarnym printf("\n Preorder :\n"); Preorder( pdrzewo ); printf("\n Postorder :\n"); Postorder( pdrzewo ); printf("\n"); } /* Funkcje pomocnicze----------------------------------------------------------------- */ ADRwezel PobierzWezel( void ) { ADRwezel p; /* zwraca adres nowego wezla */ p = (ADRwezel) malloc( sizeof( struct wezel ) ) ; return( p ); } /*------------------------------------------------------------------------------------------------*/ ADRwezel NowaGałąź( int x ) { ADRwezel p; /* wygeneruj kolejna galaz */ p = PobierzWezel(); p->info = x; p->lewy = NULL; p->prawy = NULL; return( p ); } /*------------------------------------------------------------------------------------------------*/ void PoLewej( ADRwezel p, int x ) /* wstaw liczbe x do lewej galezi */ { if ( p == NULL ) printf( "Brak pamieci !\n" ); else if ( p->lewy != NULL ) printf( "Lewy zajety !\n" ); else p->lewy = NowaGałąź( x ); } /*------------------------------------------------------------------------------------------------*/ void PoPrawej( ADRwezel p, int x) /* wstaw liczbe x do prawej galezi */ { if ( p == NULL ) printf( "Brak pamieci !\n"); else if ( p->prawy != NULL ) printf( "Prawy zajety !\n"); else p->prawy = NowaGałąź( x ); } /*------------------------------------------------------------------------------------------------*/ void Preorder( ADRwezel p ) { if ( p != NULL ) { printf(" %5d ", p->info); Preorder( p->lewy ); Preorder( p->prawy ); } } /* kolejnosc 1 */ /* info */ /* idz w lewo */ /* idz w prawo */ /*------------------------------------------------------------------------------------------------*/ void Inorder( ADRwezel p ) /* kolejnosc 2 */ { if ( p != NULL ) { Inorder( p->lewy ); /* idz w lewo */ printf(" %5d ", p->info); /* info */ Inorder( p->prawy ); /* idz w prawo */ } } /*------------------------------------------------------------------------------------------------*/ void Postorder( ADRwezel p ) { if ( p != NULL ) { Postorder( p->lewy ); Postorder( p->prawy ); printf(" %5d ", p->info); } } /* kolejnosc 3 */ /* idz w lewo */ /* idz w prawo */ /* info */