CVIČENIE 10/13 (S7) Programovanie v jazyku C

Transkript

CVIČENIE 10/13 (S7) Programovanie v jazyku C
CVIČENIE 10/13 (S7)
Programovanie v jazyku C – stromy
Binarne stromy:
-
zlozene z nula alebo viac prvkov
kazdy prvok obsahuje
o nejaku hodnotu (data)
o smernik na laveho potomka
o smernik na praveho potomka
moze byt empty
ak nie je empty ma root node
o kazdy prvok binarneho stromu je dosazitelny z korenoveho prvku po
unikatnej ceste
prvok bez potomkov je nazyvany list (leaf)
o existuju binarne stromy kde len listy obsahuju data
-
a
b
d
g
c
e
h
f
i
j
k
l
-
velkost binarneho stromu je pocet prvkov v nom (12)
hlbka prvku je vzdialenost od korena (e – 2)
hlbka stromu je maximalna vzdialenost od korena (4)
vyvazeny binarny strom – vsetky prvky okrem tych v najspodnejsie vrstve maju
dvoch potomkov
7
3
Prehladavanie v zatriedenom poli:
13
Zacni: (lo + hi)/2
2
Hladame 5:
5
(0+6)/2 = 3
hi = 2;
(0 + 2)/2 = 1
lo = 2;
(1+3)/2=2
0
1
2
3
4
5
6
2
3
5
7
1
1
1
11 17
Prechadzanie stromu:
- kazdy binarny strom je definovany rekurzivne, pomocou korenoveho nodu a laveho
podstromu a praveho podstromu
- prechadzanie takeho to stromu tak aby sme kazdy prvok navstivili prave raz je teda
rekurzivne
Preorder : root, left, right
Inorder : left, root, right
Postorder: left, right, root
Binarne stromy su vhodne napriklad na vyjadrenie vyrazov:
+
+
2
2
2
2+2
2
3
4
2+3*4
*
+
*
4
3
(2+3)*4
BINÁRNÍ STROMY
- vyhledávací stromy
prvek
1. Navrhnout datové struktury
2. Operace INSERT, SHOW, DELETE
Tato podmínka platí pro každý prvek!!
menší
prvek
větší
prvek
<
udělat INSERT bez podmínky if (vyjma při testování, zda
se naalokovala paměť)
Æ hint: každá podmínka vrací 0 nebo 1 Æ tedy int
Pozn.
- pro tisk stromu se hodí tisk několika mezer
printf(“%5c”,’a’) ... vytiskne se znak ‘a‘ na šířku 5
printf(“%*c”,k,’a’) ... vytiskne se znak ‘a‘ na šířku k
Æ pokud je šířka udána * Æ určuje počet znaků argument typu int, který musí v seznamu
argumentů bezprostředně předcházet argumentu, který se má tisknout
INSERT
- najdu místo ve stromě, kam uzel patří a tak vložím nový list
DELETE
- list ... smažu
- uzel s 1 synem ... přepojím a smažu
- uzel se 2 syny ... najdu nejpravější v levém podstromu (nebo nejlevější v pravém
podstromu) a ten uzel prohodím s mazaným uzlem
10
5
2
1
20
7
3
15
9
30
Prolézání stromu
1. pomocí if
if (x<p->x)
p = p->l;
else
p = p->r;
2. bez if
enum {left, right};
struct prvek {
int x;
prvek* dalsi[2];
}
p = p->dalsi[x > p->x];
Př. naprogramujte binární vyhledávací strom – použít pointer na pointer
- insert
- tisk stromu
- (delete)
#include <malloc.h>
#include <stdio.h>
struct prvek {
int val;
prvek* kam[2]; // v kam[0] bude ukazatel doleva, v kam[1] bude ukazatel doprava
};
struct strom {
prvek* koren;
};
// pridani prvku do stromu
int add_strom(strom* st, int x){
printf("Add %d \n",x);
prvek* n;
n = (prvek*)malloc(sizeof(prvek));
if (!n) {
printf("neni pamet");
return -1;
}
n->val = x;
n->kam[0] = NULL;
n->kam[1] = NULL;
prvek** p;
p = &(st->koren);
while (*p)
p = &((*p)->kam[x>(*p)->val]);
*p = n;
return 0;
}
// smazani prvku ve stromu
int del_strom(strom* st, int x){
printf("Del %d\n",x);
prvek** p;
prvek* tm;
prvek** tmp;
p = &(st->koren);
// prazdny strom
if (!(*p)) {
printf("prazdny strom - nelze mazat");
return -1;
}
// hledam uzel, ktery se ma smazat
while ( (*p) && ((*p)->val!=x) ) {
p = &((*p)->kam[x>(*p)->val]);
}
// uzel ve stromu neni
if (!(*p)) {
printf("prvek ve strome neni - nelze mazat \n");
return 1;
}
// uzel ve stromu JE
// - uzel “p” ma 2 syny
if( (*p)->kam[0] && (*p)->kam[1] ){
// najdu nejmensi (nejlevejsi) prvek "tmp" v pravem podstrome
tmp = &((*p)->kam[1]);
while ( (*tmp) && ((*tmp)->kam[0]) )
tmp = &((*tmp)->kam[0]);
// zkopiruju hodnotu do uzlu, ktery chci mazat
(*p)->val = (*tmp)->val;
//smazu nejlevejsi uzel v prazem podstromu (*tmp)
// - uzel (*tmp) nema leveho syna
tm = *tmp;
(*tmp) = (*tmp)->kam[1]; // prepojime praveho syna
free(tm);
}
else { // jeden ze synu uzlu “p” chybi
tm = *p;
// kdyz neni levy syn, prepojime o patro vys praveho syna
*p = (!((*p)->kam[0])) ? (*p)->kam[1] : (*p)->kam[0];
free(tm);
}
return 0;
}
// tisk jednoho prvku
int print_prvek(prvek* p){
if (p) {
if ((p->kam[0]) &&(p->kam[1]))
printf("uzel %d s L:%d a P:%d\n",p->val,p->kam[0]->val,p->kam[1]->val);
if ((!p->kam[0]) &&(p->kam[1]))
printf("uzel %d s P:%d\n",p->val,p->kam[1]->val);
if ((p->kam[0]) &&(!p->kam[1]))
printf("uzel %d s L:%d\n",p->val,p->kam[0]->val);
if ((!p->kam[0]) &&(!p->kam[1]))
printf("uzel %d \n",p->val);
print_prvek(p->kam[0]);
print_prvek(p->kam[1]);
}
return 0;
}
// tisk celeho stromu
int print_strom(strom* st){
if (!(st->koren)) {
printf("Prazdny strom \n");
return 1;
}
print_prvek(st->koren);
printf("\n\n");
return 0;
}
// inicializace stromu
strom* init_strom(){
strom* st = (strom*) malloc(sizeof(strom));
st->koren=NULL;
return st;
}
// main
int main (int argc, char** argv){
strom* tr;
tr = init_strom();
print_strom(tr);
add_strom(tr,3);
print_strom(tr);
add_strom(tr,5);
print_strom(tr);
del_strom(tr,5);
print_strom(tr);
del_strom(tr,10);
print_strom(tr);
return 0;
}
BINÁRNÍ VYVÁŽENÝ VYHLEDÁVACÍ STROM
- binární vyhledávací strom
- pro každý uzel platí navíc podmínka, že výška v pravém a levém podstromu se liší
nejvýše o 1
3. DOMÁCÍ ÚKOL
Př. program, který načte jako parametry příkazy pro práci s binárním stromem
ix ... vloží prvek s hodnotou “x“ do binárního stromu
dx ... vybere prvek s hodnotou “x“ z binárního stromu
např. myprog i4 d4 i8 i9 d7
Možná struktura main:
int main (int argc, char** argv){
char* param;
.....
argv++; // posuneme se na prvni skutečný parametr;
// dokud mame nejaky parametr
while (*argv){
switch (**argv){ // switch podle prvního znaku v parametru
case 'i':
.....
break;
case 'd':
......
break;
}
argv++;
}
return 0;
}
Řešení main:
int main (int argc, char** argv){
strom* tr;
tr = init_strom();
argv++; // posuneme se na prvni parametr;
// dokud mame nejaky parametr
while (*argv){
switch (**argv){
case 'i':
add_strom(tr,atoi(*argv+1));
print_strom(tr);
break;
case 'd':
del_strom(tr,atoi(*argv+1));
print_strom(tr);
break;
}
argv++;
}
return 0;
}

Podobné dokumenty

Lion 2

Lion 2 Pokial' 5TB neobd rzf ziade n prf kaz ce z pred ny p anel alebo d ial'kovy o vladac po dob u od 30min ­ 3 hod a po kial' s a nesp ustf ziad na udalost c aso vaca ­ 5T B prejde autom aticky do pohot...

Více

ADS3-SG

ADS3-SG Poznámka : Někdy se z definice téměř úplných binárních stromů vypouští podmínka, že se musí jednat o striktně binární strom. Potom bychom mohli považovat za téměř úplný binární strom např. i takovo...

Více

Jak překládat do angličtiny abstrakty publikovaných prací z oboru

Jak překládat do angličtiny abstrakty publikovaných prací z oboru z oboru fotogrammetrie a dálkový průzkum Země Neodmyslitelnou součástí publikace vědeckého sdělení, referátu, článku či monografie z oboru fotogrammetrie a dálkového průzkumu Země je anglická verze...

Více

B17 WRECK Boeing B17 American bomber 42° 34.232` N 08

B17 WRECK Boeing B17 American bomber 42° 34.232` N 08 V roku 1944 B17 bol na misii v Taliansku. Bohuzial bol zasiahnuty nemeckymi stihackami. Bez akehokolvek radia a navigacie, pilot Frank Chaplick sa rozhodol letiet na Calvi. Pristavacia draha bola p...

Více

Výpisky z přednášek

Výpisky z přednášek Jde pouze pro acyklické grafy (žádný cyklus a smyčka). Uzly můžeme seřadit do horizontální úrovně a orientace všech hran pak musí směřovat jedním směrem. Získání: pomocí DFS prohledej a v okamžiku ...

Více

Úvod do jazyka C++

Úvod do jazyka C++ načíst hodnota ze vstupu (tj. zpravidla z klávesnice) ● Hodnota na vstupu musí odpovídat typu proměnné (celé číslo, reálné číslo, znak) ● Při čtení se přeskakují bílé znaky (mezery, tabelátory, zna...

Více