BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

Podobné dokumenty
Spojové struktury. Spojová struktura (linked structure):

Spojové struktury. x, y, a, b. X1 y1 X2 y2 X3 y3. Grafické objekty bod. kružnice. obdélník. lomenáčára

Funkce, intuitivní chápání složitosti

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

Stromy. Strom: souvislý graf bez kružnic využití: počítačová grafika seznam objektů efektivní vyhledávání výpočetní stromy rozhodovací stromy

Rozklad problému na podproblémy, rekurze

Rozklad problému na podproblémy, rekurze

Např.: // v hlavičkovém souboru nebo na začátku // programu (pod include): typedef struct { char jmeno[20]; char prijmeni[20]; int rok_nar; } CLOVEK;

- jak udělat konstantu long int: L long velka = 78L;

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE REALIZACE PŘEKLADAČE I

Jazyk C++, některá rozšíření oproti C

Dynamicky vázané metody. Pozdní vazba, virtuální metody

Řídící struktury, if, while, switch

Abstraktní třídy, polymorfní struktury

Stromy. Jan Hnilica Počítačové modelování 14

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

Lineární spojový seznam (úvod do dynamických datových struktur)

Mělká a hluboká kopie

Rekurzivní algoritmy

9. lekce Úvod do jazyka C 4. část Funkce, rekurze Editace, kompilace, spuštění Miroslav Jílek

Program převod z desítkové na dvojkovou soustavu: /* Prevod desitkove na binarni */ #include <stdio.h>

Operační systémy. Cvičení 4: Programování v C pod Unixem

Základní datové struktury

Př. další použití pointerů

Algoritmy a datové struktury

2) Napište algoritmus pro vložení položky na konec dvousměrného seznamu. 3) Napište algoritmus pro vyhledání položky v binárním stromu.

Datové struktury. alg12 1

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Řídící struktury, if, while, switch

Programování v C++ 1, 1. cvičení

Abstraktní datové typy

int ii char [16] double dd název adresa / proměnná N = nevyužito xxx xxx xxx N xxx xxx N xxx N

PROGRAMOVACÍ JAZYKY A PŘEKLADAČE LEXIKÁLNÍ ANALÝZA

4. Rekurze. BI-EP1 Efektivní programování Martin Kačer

Konstruktory a destruktory

Programování v C++ 3, 3. cvičení

Dynamické datové struktury III.

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

BI-EP1 Efektivní programování 1

Algoritmizace a programování

Algoritmizace Dynamické programování. Jiří Vyskočil, Marko Genyg-Berezovskyj 2010

5 Rekurze a zásobník. Rekurzivní volání metody

Základní pojmy. Úvod do programování. Základní pojmy. Zápis algoritmu. Výraz. Základní pojmy

Základní datové struktury III: Stromy, haldy

Programování v C++, 2. cvičení

Programování v C++ 1, 16. cvičení

Algoritmizace a programování

Spojová implementace lineárních datových struktur

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Větvení a cykly. Úvod do programování 1 Tomáš Kühr

Dynamické datové struktury I.

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky

int t1, t2, t3, t4, t5, t6, t7, prumer; t1=sys.readint();... t7=sys.readint(); prume pru r = r = ( 1+t 1+t t3+ t3+ t4 t5+ t5+ +t7 +t7 )/ ;

Dynamické datové typy a struktury

ZÁPOČTOVÝ TEST. Zpracoval Vilém Závodný, #include "stdafx.h" #include "stdio.h"

Datové struktury. Obsah přednášky: Definice pojmů. Abstraktní datové typy a jejich implementace. Algoritmizace (Y36ALG), Šumperk - 12.

1. lekce. do souboru main.c uložíme následující kód a pomocí F9 ho zkompilujeme a spustíme:

Základy algoritmizace a programování

Lekce 19 IMPLEMENTACE OPERAČNÍHO SYSTÉMU LINUX DO VÝUKY INFORMAČNÍCH TECHNOLOGIÍ JAZYK C

Stromy. Karel Richta a kol. Katedra počítačů Fakulta elektrotechnická České vysoké učení technické v Praze Karel Richta a kol.

Binární vyhledávací strom pomocí směrníků Miroslav Hostaša L06620

Základy programování (IZP)

Úvod do programovacích jazyků (Java)

for (i = 0, j = 5; i < 10; i++) { // tělo cyklu }

Racionální čísla, operátory, výrazy, knihovní funkce

Algoritmizace a programování

Základy programování (IZP)

2 Datové typy v jazyce C

Michal Krátký. Úvod do programovacích jazyků (Java), 2006/2007

B3B33ALP - Algoritmy a programování - Zkouška z předmětu B3B33ALP. Marek Boháč bohacm11

8. lekce Úvod do jazyka C 3. část Základní příkazy jazyka C Miroslav Jílek

Stromy. Příklady. Rekurzivní datové struktury. Základní pojmy

Zápis programu v jazyce C#

Další příklady. Katedra softwarového inženýrství. Katedra teoretické informatiky, Fakulta informačních technologii, ČVUT v Praze. Karel Müller, 2011

Algoritmy výpočetní geometrie

Odvozené a strukturované typy dat

Řídicí struktury. alg3 1

ADT/ADS = abstraktní datové typy / struktury

BI-PA1 Programování a algoritmizace 1, ZS Katedra teoretické informatiky

Úvod do jazyka C. Ing. Jan Fikejz (KST, FEI) Fakulta elektrotechniky a informatiky Katedra softwarových technologií

Strukturované typy a ukazatele. Úvod do programování 1 Tomáš Kühr

ALGORITMIZACE 2010/03 STROMY, BINÁRNÍ STROMY VZTAH STROMŮ A REKURZE ZÁSOBNÍK IMPLEMENTUJE REKURZI PROHLEDÁVÁNÍ S NÁVRATEM (BACKTRACK)

Stromy, haldy, prioritní fronty

Rozklad problému na podproblémy

Programování v jazyce C pro chemiky (C2160) 3. Příkaz switch, příkaz cyklu for, operátory ++ a --, pole

Začínáme vážně programovat. Řídící struktury Přetypování Vstupně výstupní operace Vlastní tvorba programů

Reprezentace dat v informačních systémech. Jaroslav Šmarda

Automaty a gramatiky(bi-aag) Formální překlady. 5. Překladové konečné automaty. h(ε) = ε, h(xa) = h(x)h(a), x, x T, a T.

Dynamické datové struktury IV.

Úvod do programování - Java. Cvičení č.4

Programovanie v jazyku C - to chce dynamiku

Prezentace a vysvětlení programového prostředí NXC

Základy algoritmizace c2005, 2007 Michal Krátký, Jiří Dvorský1/39

1. D Y N A M I C K É DAT O V É STRUKTUR Y

Implementace LL(1) překladů

Algoritmizace prostorových úloh

11b Další příklady operací vstupu a výstupu (úvod viz 10)

Transkript:

Evropský sociální fond Praha & EU: Investujeme do vaší budoucnosti Spojové struktury BI-PA1 Programování a algoritmizace 1 Katedra teoretické informatiky Miroslav Balík Fakulta informačních technologií České vysoké učení technické v Praze

Téma shrnutí typu struktura Obsah spojové seznamy vložení nového prvku na začátek spojového seznamu průchod spojovým seznamem vložení nového prvku na konec spojového seznamu stromy příklad binárního stromu 2/31

Syntaxe popisu struktury: Shrnutí typu struktura struct značka { seznam popisů položek Popisy položek mají podobný tvar, jako deklarace proměnných položka nesmí být typu stejná struktura položka může být ukazatelem na stejnou strukturu struct osoba { char jmeno[20]; char prijmeni[25]; int rok_narozeni; ; /* deklarace struktury */ struct osoba Jan; /* deklarace proměnné typu struct osoba */ Značka struktury není identifikátorem typu osoba Petr; /* chyba */ 3/31

Shrnutí typu struktura Identifikátor typu lze pro strukturu zavést deklarací typu typedef struct Complex {float Real, Imag; Complex; Complex a, b; /* O.K. */ Zpřístupnění položky struktury: Přímá selekce: X. položka kde X je výraz typu struct Nepřímá selekce (přes ukazatel): X -> položka kde X je výraz typu ukazatel na struct X -> položka je zkratkou za (*X). položka struct { int a; char b; x, *px = &x; x.a = 1; px -> b = a ; (*px).b = a ; /* totéž */ 4/31

Úvodní příklad na spojové seznamy Program, který přečte řadu celých čísel zakončených nulou a vypíše je v opačném pořadí (bez závěrečné nuly) Úlohu jsme řešili: pomocí rekurzivní procedury (nebylo třeba omezit počet čísel) pomocí pole (bylo třeba omezit počet čísel) Vyřešme ji pomocí dynamických proměnných, z nichž vytvoříme spojový seznam (nebude potřeba omezit počet čísel). Princip: pro každé přečtené číslo dynamicky vytvoříme proměnnou typu struktura, v jejíž jedné položce bude číslo a ve druhé ukazatel na další proměnnou obsahující dříve přečtené číslo Příklad: pro vstupní posloupnost 15 5 10 0 vytvoříme: dynamicky vytvořené proměnné 10 5 15 5/31

Úvodní příklad na spojové seznamy Dynamicky vytvářené proměnné budou typu Prvek: typedef struct prvek { int hodn; struct prvek *dalsi; Prvek; Pro vytvoření dynamické proměnné typu Prvek zavedeme funkci: Prvek *vytvorprvek(int hodn, Prvek *dalsi) { Prvek *pom = (Prvek*)malloc(sizeof(Prvek)); pom->hodn = hodn; pom->dalsi = dalsi; return pom; Ukazatelem na první prvek spojového seznamu bude proměnná Prvek *zacatek = NULL; lépe sizeof(*pom), velikost vypočítá překladač (od C99 až za běhu) podle proměnné, odolnější proti chybě programátora 6/31

Úvodní příklad na spojové seznamy Postup při vytvoření spojového seznamu: pokud přečtené číslo není nula, pak uložíme ho do dynamicky vytvořené proměnné typu Prvek, která v položce další bude obsahovat ukazatel na začátek doposud vytvořeného spojového seznamu ukazatel na novou proměnnou typu Prvek se stane ukazatelem na rozšířený spojový seznam skončíme, když je přečtené číslo nula pak spojový seznam projdeme od začátku do konce a čísla vypíšeme 7/31

Úvodní příklad - prog12-seznam1.c int main(void) { Prvek *zacatek = NULL, *p; int cislo; printf("zadej posloupnost cisel zakoncenou nulou\n"); scanf("%d", &cislo); while (cislo) { zacatek = vytvorprvek(cislo, zacatek); scanf("%d", &cislo); printf("vypis cisel v opacnem poradi\n"); p = zacatek; while (p) { printf("%d ", p->hodn); p = p->dalsi;...+uvolnění seznamu printf("\n"); system("pause"); return 0; 8/31

Druhý příklad Úvodní příklad ilustroval: vytváření spojového seznamu vkládáním prvku na začátek průchod spojovým seznamem a provedení operace pro všechny prvky Další příklad na průchod spojovým seznamem (prog12-seznam2.c): přečteme čísla zakončená nulou vytvoříme z nich spojový seznam (vkládáním prvku na začátek seznamu) pak čteme další posloupnost čísel zakončenou nulou pro každé číslo vypíšeme, zda je či není prvkem spojového seznamu 9/31

Druhý příklad Funkce pro výpis seznamu void vypisseznamu(prvek *p) { while (p) { printf("%d ", p->hodn); p = p->dalsi; printf("\n"); Funkce pro hledání hodnoty v seznamu int jeprvkem(prvek *p, int x) { while (p && p->hodn!=x) p = p->dalsi; if (p) return 1; else return 0; 10/31

Druhý příklad funkce main int main(void) { Prvek *zacatek = NULL, *p; int cislo; printf("zadej posloupnost cisel zakoncenou nulou\n"); scanf("%d", &cislo); while (cislo) { zacatek = vytvorprvek(cislo, zacatek); scanf("%d", &cislo); printf("vypis cisel v opacnem poradi\n"); vypisseznamu(zacatek); printf("zadej dalsi posloupnost cisel zakoncenou nulou\n");... 11/31

... Druhý příklad funkce main, 2. část printf("zadej dalsi posloupnost cisel zakoncenou nulou\n"); scanf("%d", &cislo); while (cislo) { printf("cislo %d ", cislo); if (jeprvkem(zacatek, cislo)) printf("je "); else printf("neni "); printf("prvkem seznamu\n"); scanf("%d", &cislo); printf("\n"); system("pause"); return 0; 12/31

Vložení prvku na konec spojového seznamu I 1. přečteme posloupnost čísel zakončenou nulou 2. vytvoříme spojový seznam, ve kterém budou čísla v pořadí, v jakém jsou čtena 3. seznam vypíšeme Seznam budeme vytvářet vkládáním nového prvku na konec K vložení na konec musíme najít poslední prvek seznamu poslední prvek má v položce dalsi hodnotu NULL na počátku je seznam prázdný, tj. zacatek je NULL Zavedeme funkci: Prvek *najdiposledni(prvek *p) { if (!p) return NULL; while (p->dalsi) p = p->dalsi; return p; 13/31

Vložení prvku na konec spojového seznamu I /*prog12-seznam3a.c*/ int main(void) { Prvek *zacatek = NULL, *posledni, *p; int cislo; printf("zadej posloupnost cisel zakoncenou nulou\n"); scanf("%d", &cislo); while (cislo) { p = vytvorprvek(cislo, NULL); posledni = najdiposledni(zacatek); if (posledni) posledni->dalsi = p; else zacatek = p; scanf("%d", &cislo); printf("vypis cisel\n"); vypisseznamu(zacatek); system("pause"); return 0; 14/31

Vložení prvku na konec spojového seznamu II Pokud při vkládání prvku na konec spojového seznamu hledáme poslední prvek, má operace vložení lineární časovou složitost O(n) Poznámka: operace vložení prvku na začátek spojového seznamu má konstantní časovou složitost O(1) int main(void) {... Prvek *zacatek = NULL, *posledni = NULL, *p; int cislo; scanf("%d", &cislo); while (cislo) { p = vytvorprvek(cislo, NULL); if (posledni) posledni->dalsi = p; else zacatek = p; posledni = p; scanf("%d", &cislo); Vložení prvku na konec spojového seznamu bude mít konstantní složitost, budeme-li si pamatovat ukazatel na poslední prvek (prog12-seznam3b.c) 15/31

Spojové struktury Spojový seznam z předchozích příkladů patří mezi spojové struktury Spojová struktura (linked structure): množina objektů propojených pomocí spojů (ukazatelů) Spoj často vyjadřuje vztah předchůdce následník Lineární spojové struktury (spojové seznamy): každý prvek struktury má nanejvýš jednoho následníka Příklady spojových seznamů: jednosměrný dvousměrný cyklický jednosměrný 16/31

Nelineární spojová struktura: Stromy každý prvek může mít více následníků Příkladem nelineární spojové struktury je strom (prvky nazýváme uzly) Binární strom: kořen stromu každý uzel má nanejvýš dva následníky levý podstrom pravý podstrom list 17/31

Realizace binárního stromu Struktura uzlů: Příklad binárního stromu: 18/31

Příklad dekódování morseovky Pro dekódování textu zapsaného v Morseově abecedě lze použít následující binární strom. -. E - T. - I A N M. -. -. -. - S U R W D K Z O. -... -. -. -. - H V F L P J B X C Y Z Q 19/31

Příklad dekódování morseovky Strom vytvoříme ze struktur typu Muzel typedef struct MUzel { char znak; struct MUzel *tecka, *carka; MUzel; a pomocí funkcí: MUzel *novymuzel(char z, MUzel *t, MUzel *c) { MUzel *p = (MUzel*)malloc(sizeof(MUzel)); p->znak = z; p->tecka = t; p->carka = c; return p; MUzel *novymuzel1(char z) { MUzel *p = (MUzel*)malloc(sizeof(MUzel)); p->znak = z; p->tecka = NULL; p->carka = NULL; return p; 20/31

Dekódování morseovky, vytvoření stromu MUzel *strom(void) { return novymuzel(' ', novymuzel('e', /*. */ novymuzel('i', /*.. */ novymuzel('s', /*... */ novymuzel1('h'), /*... */ novymuzel1('v') /*...- */ ), novymuzel('u', /*..- */ novymuzel1('f'), /*..-. */ NULL /*..-- */ )), novymuzel('a', /*.- */...)), novymuzel('t', /* - */...)); 21/31

Příklad dekódování morseovky Prvním parametrem je řetěz obsahující Morseův kód zakončený mezerou a druhým je pole, kam se uloží dekódovaný text void dekoduj(char odkud[], char kam[]) { MUzel *aktualni = koren; int i = 0, j = 0, delka = strlen(odkud); while (i<delka) { char z = odkud[i]; if (aktualni!=null) { if (z=='.') aktualni = aktualni->tecka; else if (z=='-') aktualni = aktualni->carka; else { kam[j++] = aktualni->znak; aktualni = koren; i++; else { kam[j++] = '?'; while (odkud[i]=='.' odkud[i]=='-') i++; aktualni = koren; kam[j] = 0; 22/31

Dekódování morseovky - main /* prog12-morseovka.c*/ MUzel *koren; #define MAXDELKA 100 int main(void) { koren = strom(); char morse[maxdelka], text[maxdelka]; fgets(morse, MAXDELKA, stdin); dekoduj(morse, text); /* + ukliď strom*/ fprintf(stdout, "%s\n", text); system("pause"); return 0; 23/31

Příklad - hra Jaké zvíře si myslíš Příklad dialogu počítače a člověka : Myslite si nejake zvire? ano leta? ne Je to ryba? ne Neuhadl jsem. Prosim o doplneni znalosti. Jake zvire jste myslel? pes Napiste otazku vystihujici rozdil mezi pes a ryba steka Pro pes je odpoved ano ci ne ano Dekuji, chcete pokracovat?... pro zájemce 24/31

Příklad - hra Jaké zvíře si myslíš Počáteční strom : Strom po doplnění znalostí: pro zájemce 25/31

Jaké zvíře si myslíš -hrubé řešení "úvod dialogu"; "aktuálním uzlem je kořen stromu"; do { "polož otázku uvedenou v aktuálním uzlu"; if ("odpověď je ano") "aktuálním uzlem je levý následník" else "aktuálním uzlem je pravý následník" while ("aktuální uzel není list"); "polož závěrečnou otázku, název zvířete vyber z aktuálního uzlu"; if ("odpověď je ano") "hádání bylo úspěšné" else { "hádání bylo neúspěšné"; "doplň znalosti" pro zájemce 26/31

Jaké zvíře si myslíš uzel a vytvoření typedef struct Uzel { char text[maxdelka]; struct Uzel *ano, *ne; Uzel; Uzel *vytvoruzel1(char t[]) { Uzel *u = (Uzel*)malloc(sizeof(Uzel)); strcpy(u->text, t); u->ano = NULL; u->ne = NULL; return u; Uzel *vytvoruzel(char t[], Uzel *a, Uzel *n) { Uzel *u = (Uzel*)malloc(sizeof(Uzel)); strcpy(u->text, t); u->ano = a; u->ne = n; return u; pro zájemce 27/31

Jaké zvíře si myslíš Test, zda uzel je listem, inicializaci stromu a čtení odpovědi: int jelist(uzel *u) { return u->ano==null && u->ne==null; Uzel *inicializacestromu() { return vytvoruzel("leta?", vytvoruzel1("ptak"), vytvoruzel1("ryba") ); int odpovedano() { char odpoved[maxdelka]; scanf("%s", odpoved); if (odpoved[0]=='a' odpoved[0]=='a') return 1; else return 0; pro zájemce 28/31

Jaké zvíře si myslíš main /* prog12-hra.c */ int main() { Uzel *koren = inicializacestromu(); for (;;) { printf("myslite si nejake zvire?\n"); if (!odpovedano()) break; Uzel *aktualni = koren; do { printf("%s\n", aktualni->text); if (odpovedano()) aktualni = aktualni->ano; else aktualni = aktualni->ne; while (!jelist(aktualni)); printf("je to %s?\n", aktualni->text); if (odpovedano()) printf("uhadl jsem\n"); else { printf("neuhadl jsem. Prosim o doplneni znalosti\n"); doplnpodstrom(aktualni); printf("dekuji. Chcete pokracovat?\n"); if (!odpovedano()) break; return 0; pro zájemce 29/31

Jaké zvíře si myslíš - doplnění znalostí: void doplnpodstrom(uzel *p) { char novezvire[maxdelka], novaotazka[maxdelka]; Uzel *novyano, *novyne; printf("jake zvire jste myslel?\n"); scanf("%s", novezvire); printf("napiste otazku vystihujici rozdil mezi %s a %s\n", novezvire, p->text); scanf("%s", novaotazka); printf("pro %s je odpoved ano ci ne?\n", novezvire); if (odpovedano()) { novyano = vytvoruzel1(novezvire); novyne = vytvoruzel1(p->text); else { novyano = vytvoruzel1(p->text); novyne = vytvoruzel1(novezvire); strcpy(p->text, novaotazka); p->ano = novyano; p->ne = novyne; pro zájemce 30/31

Jaké zvíře si myslíš - prog12-hra.c int main() { Uzel *koren = inicializacestromu(); for (;;) { printf("myslite si nejake zvire?\n"); if (!odpovedano()) break; Uzel *aktualni = koren; do { printf("%s\n", aktualni->text); if (odpovedano()) aktualni = aktualni->ano; else aktualni = aktualni->ne; while (!jelist(aktualni)); printf("je to %s?\n", aktualni->text); if (odpovedano())printf("uhadl jsem\n"); else { printf("neuhadl jsem. Prosim o doplneni znalosti\n"); doplnpodstrom(aktualni); printf("dekuji. Chcete pokracovat?\n"); if (!odpovedano()) break; return 0; pro zájemce 31/31