DRZEWADRZEWA
PRZEDZIAŁOWEPRZEDZIAŁOWE
CZYM JEST DRZEWOCZYM JEST DRZEWO
 Drzewo to obiekt w teorii grafów, który nie maDrzewo to obiekt w teorii grafów, który nie ma
cykli i jest spójny, tzn:cykli i jest spójny, tzn:
 wychodząc z wierzchołka A nie da się do niego powrócić (przywychodząc z wierzchołka A nie da się do niego powrócić (przy
czym jeśli w pierwszym kroku wykonujemy ruch Aczym jeśli w pierwszym kroku wykonujemy ruch A → B, to w→ B, to w
drugim nie możemy wykonaćdrugim nie możemy wykonać BB → A,→ A, A i B są dowolnymiA i B są dowolnymi
wierzchołkami grafuwierzchołkami grafu))
 z dowolnego wierzchołka A można w skończonej ilości krokówz dowolnego wierzchołka A można w skończonej ilości kroków
przejść do dowolnego wierzchołka Bprzejść do dowolnego wierzchołka B
Widzimy, że graf ten jestWidzimy, że graf ten jest
spójny, ale posiada cyklspójny, ale posiada cykl
(1(1→2→5→1), zatem nie jest→2→5→1), zatem nie jest
drzewemdrzewem
Z kolei ten graf jest zarównoZ kolei ten graf jest zarówno
spójny i acykliczny, zatem jestspójny i acykliczny, zatem jest
drzewemdrzewem
TERMINOLOGIATERMINOLOGIA
 Dla dowolnej ścieżki prostej rozpoczynającej się
od korzenia i zawierającej wierzchołek V:
 wierzchołki występujące w ścieżce przed V nazywamy przodkami
V, a wierzchołki występujące po - potomkami V
 wierzchołek poprzedzający V nazywamy rodzicem lub ojcem, a
będący bezpośrednio po - dzieckiem lub synem.
 wierzchołki mające wspólnego ojca nazywamy braćmi
 Wierzchołki, które nie mają synów nazywamy liśćmi .
 Najdłuższą ścieżkę w drzewie
nazywamy średnicą drzewa.
 Drzewo z wyróżnionym wierzchołkiem,
korzeniem, nazywamy drzewem ukorzenionym.
DRZEWO W INFORMATYCEDRZEWO W INFORMATYCE
 W informatyce jest to struktura danych, któraW informatyce jest to struktura danych, która
reprezentuje drzewo jako obiekt teorii grafów.reprezentuje drzewo jako obiekt teorii grafów.
 Umożliwia szybkie wykonanie algorytmów:Umożliwia szybkie wykonanie algorytmów:
 Sprawdzenie wartości elementu [w czasie O(log n)]Sprawdzenie wartości elementu [w czasie O(log n)]
 Zmianę wartości elementu [w czasie O(log n)]Zmianę wartości elementu [w czasie O(log n)]
 Znalezienie maksimum i minimum w przedziale [w czasie O(logZnalezienie maksimum i minimum w przedziale [w czasie O(log
n)]n)]
 Zwiększenie wszystkich elementów w przedziale o pewnąZwiększenie wszystkich elementów w przedziale o pewną
wartość [w czasie O(log n)]wartość [w czasie O(log n)]
DRZEWA BINARNEDRZEWA BINARNE
 Jest to struktura danych będąca drzewem, którejJest to struktura danych będąca drzewem, której
wierzchołki mają co najwyżej 2 stopień.wierzchołki mają co najwyżej 2 stopień.
Interesujące dla nas są jednak jego pochodneInteresujące dla nas są jednak jego pochodne
 Drzewo binarne poszukiwańDrzewo binarne poszukiwań jestjest
dynamiczną strukturą danych zbudowanądynamiczną strukturą danych zbudowaną
zz węzłówwęzłów . Każdy węzeł może posiadać. Każdy węzeł może posiadać
dwóch potomków (dwóch potomków (lewylewy ii prawyprawy) oraz) oraz
jednegojednego przodkaprzodka. Z każdym węzłem. Z każdym węzłem
dodatkowo związany jestdodatkowo związany jest kluczklucz..
 Binarne drzewa wyszukiwań częstoBinarne drzewa wyszukiwań często
stosuje się w zadaniach, w którychstosuje się w zadaniach, w których
wymagane jest względnie szybkiewymagane jest względnie szybkie
sortowanie lub wyszukiwanie elementów.sortowanie lub wyszukiwanie elementów.
#include <stdlib.h>#include <stdlib.h>
#include <stdio.h>#include <stdio.h>
#include <string.h>#include <string.h>
struct node{struct node{
int key;int key;
struct node *lewy;struct node *lewy;
struct node *prawy;struct node *prawy;
}*korzen=NULL;}*korzen=NULL;
void push(struct node *&korzen,int x)void push(struct node *&korzen,int x)
{{
if(korzen==NULL)if(korzen==NULL)
{{
korzen=(struct node*)malloc(sizeof(struct node));korzen=(struct node*)malloc(sizeof(struct node));
korzen->lewy=NULL;korzen->lewy=NULL;
korzen->prawy=NULL;korzen->prawy=NULL;
korzen->key=x;korzen->key=x;
return;return;
}else}else
{{
if(x<(korzen->key))if(x<(korzen->key))
push(korzen->lewy,x);push(korzen->lewy,x);
else push(korzen->prawy,x);else push(korzen->prawy,x);
}}
}}
void showrek(struct node *korzen) //lewe poddrzewo,void showrek(struct node *korzen) //lewe poddrzewo,
prawe,rekurencyjnieprawe,rekurencyjnie
{{
if(korzen)if(korzen)
{{
showrek(korzen->lewy);showrek(korzen->lewy);
showrek(korzen->prawy);showrek(korzen->prawy);
printf("%d ",korzen->key);printf("%d ",korzen->key);
}}
}}
int main()int main()
{{
int n,i,x;int n,i,x;
printf("Ile elementow dodad do drzewa??n");printf("Ile elementow dodad do drzewa??n");
scanf("%d",&n);scanf("%d",&n);
i=0;i=0;
while(i!=n)while(i!=n)
{{
printf("Element nr%d: ",i+1);printf("Element nr%d: ",i+1);
scanf("%d",&x);scanf("%d",&x);
push(korzen,x);push(korzen,x);
i++;i++;
}}
showrek(korzen);showrek(korzen);
system("PAUSE");system("PAUSE");
}}
 Drzewo przedziałoweDrzewo przedziałowe, struktura danych, struktura danych
przechowująca punkty, oraz związane z tymiprzechowująca punkty, oraz związane z tymi
punktami wszystkie możliwe przedziały. Drzewopunktami wszystkie możliwe przedziały. Drzewo
przedziałowe, jeśli jest skonstruowane tak, abyprzedziałowe, jeśli jest skonstruowane tak, aby
było zrównoważone, pozwala odpowiadać nabyło zrównoważone, pozwala odpowiadać na
zapytania o dowolny przedział w czasiezapytania o dowolny przedział w czasie
logarytmicznym.logarytmicznym.
#include <iostream>#include <iostream>
using namespace std;using namespace std;
const int MAXN = 1048576;const int MAXN = 1048576;
int n, a[MAXN], intervalTree[2*MAXN];int n, a[MAXN], intervalTree[2*MAXN];
void read() {void read() {
cin >> n;cin >> n;
for(int i=0;i<n;i++) cin >> a[i];for(int i=0;i<n;i++) cin >> a[i];
}}
void buildTree(int node) {void buildTree(int node) {
if(node >= MAXN) { //sprawdzam czy node jest liściemif(node >= MAXN) { //sprawdzam czy node jest liściem
intervalTree[node] = a[node-MAXN];intervalTree[node] = a[node-MAXN];
return; //zawracam, żeby nie wyjść poza zakres danychreturn; //zawracam, żeby nie wyjść poza zakres danych
}}
buildTree(node*2);buildTree(node*2);
buildTree(node*2+1);buildTree(node*2+1);
intervalTree[node] = intervalTree[node*2]+intervalTree[node*2+1]; //obliczamintervalTree[node] = intervalTree[node*2]+intervalTree[node*2+1]; //obliczam
wartość w wierzchołku na podstawie synówwartość w wierzchołku na podstawie synów
}}
int query(int f, int s) { //query już jest iteracyjnyint query(int f, int s) { //query już jest iteracyjny
f = f+MAXN; s = s+MAXN;f = f+MAXN; s = s+MAXN;
if(f == s) return intervalTree[s];if(f == s) return intervalTree[s];
int res = intervalTree[f]+intervalTree[s];int res = intervalTree[f]+intervalTree[s];
while(f/2 != s/2) {while(f/2 != s/2) {
if(f%2 == 0) res = res+intervalTree[f+1];if(f%2 == 0) res = res+intervalTree[f+1];
if(s%2 == 1) res = res+intervalTree[s-1];if(s%2 == 1) res = res+intervalTree[s-1];
f = f/2; s = s/2;f = f/2; s = s/2;
}}
return res;return res;
void update(int f, int s) { //podstawiam a[f] := svoid update(int f, int s) { //podstawiam a[f] := s
int restore = a[f-1];int restore = a[f-1];
a[f-1] = s;a[f-1] = s;
f += MAXN-1;f += MAXN-1;
while(f != 0) {while(f != 0) {
intervalTree[f] += s-restore;intervalTree[f] += s-restore;
f = f/2;f = f/2;
}}
}}
int main() {int main() {
read();read();
buildTree(1); //zaczynamy od korzenia i budujemybuildTree(1); //zaczynamy od korzenia i budujemy
rekurencyjnierekurencyjnie
while(1) {while(1) {
char operationType; int f, s; //typ operacji: Q -char operationType; int f, s; //typ operacji: Q -
zapytanie o sumę (f,s), U - zamienia a[f] na s, E - exitzapytanie o sumę (f,s), U - zamienia a[f] na s, E - exit
cin >> operationType >> f >> s;cin >> operationType >> f >> s;
if(operationType == 'Q') cout << query(f-1,s-1) <<if(operationType == 'Q') cout << query(f-1,s-1) <<
endl; //indeksuje od 0endl; //indeksuje od 0
if(operationType == 'U') update(f,s);if(operationType == 'U') update(f,s);
if(operationType == 'E') return 0;if(operationType == 'E') return 0;
}}
return 0;return 0;
}}

Drzewa przedziałowe

  • 1.
  • 2.
    CZYM JEST DRZEWOCZYMJEST DRZEWO  Drzewo to obiekt w teorii grafów, który nie maDrzewo to obiekt w teorii grafów, który nie ma cykli i jest spójny, tzn:cykli i jest spójny, tzn:  wychodząc z wierzchołka A nie da się do niego powrócić (przywychodząc z wierzchołka A nie da się do niego powrócić (przy czym jeśli w pierwszym kroku wykonujemy ruch Aczym jeśli w pierwszym kroku wykonujemy ruch A → B, to w→ B, to w drugim nie możemy wykonaćdrugim nie możemy wykonać BB → A,→ A, A i B są dowolnymiA i B są dowolnymi wierzchołkami grafuwierzchołkami grafu))  z dowolnego wierzchołka A można w skończonej ilości krokówz dowolnego wierzchołka A można w skończonej ilości kroków przejść do dowolnego wierzchołka Bprzejść do dowolnego wierzchołka B
  • 3.
    Widzimy, że graften jestWidzimy, że graf ten jest spójny, ale posiada cyklspójny, ale posiada cykl (1(1→2→5→1), zatem nie jest→2→5→1), zatem nie jest drzewemdrzewem Z kolei ten graf jest zarównoZ kolei ten graf jest zarówno spójny i acykliczny, zatem jestspójny i acykliczny, zatem jest drzewemdrzewem
  • 4.
    TERMINOLOGIATERMINOLOGIA  Dla dowolnejścieżki prostej rozpoczynającej się od korzenia i zawierającej wierzchołek V:  wierzchołki występujące w ścieżce przed V nazywamy przodkami V, a wierzchołki występujące po - potomkami V  wierzchołek poprzedzający V nazywamy rodzicem lub ojcem, a będący bezpośrednio po - dzieckiem lub synem.  wierzchołki mające wspólnego ojca nazywamy braćmi  Wierzchołki, które nie mają synów nazywamy liśćmi .  Najdłuższą ścieżkę w drzewie nazywamy średnicą drzewa.  Drzewo z wyróżnionym wierzchołkiem, korzeniem, nazywamy drzewem ukorzenionym.
  • 5.
    DRZEWO W INFORMATYCEDRZEWOW INFORMATYCE  W informatyce jest to struktura danych, któraW informatyce jest to struktura danych, która reprezentuje drzewo jako obiekt teorii grafów.reprezentuje drzewo jako obiekt teorii grafów.  Umożliwia szybkie wykonanie algorytmów:Umożliwia szybkie wykonanie algorytmów:  Sprawdzenie wartości elementu [w czasie O(log n)]Sprawdzenie wartości elementu [w czasie O(log n)]  Zmianę wartości elementu [w czasie O(log n)]Zmianę wartości elementu [w czasie O(log n)]  Znalezienie maksimum i minimum w przedziale [w czasie O(logZnalezienie maksimum i minimum w przedziale [w czasie O(log n)]n)]  Zwiększenie wszystkich elementów w przedziale o pewnąZwiększenie wszystkich elementów w przedziale o pewną wartość [w czasie O(log n)]wartość [w czasie O(log n)]
  • 6.
    DRZEWA BINARNEDRZEWA BINARNE Jest to struktura danych będąca drzewem, którejJest to struktura danych będąca drzewem, której wierzchołki mają co najwyżej 2 stopień.wierzchołki mają co najwyżej 2 stopień. Interesujące dla nas są jednak jego pochodneInteresujące dla nas są jednak jego pochodne
  • 7.
     Drzewo binarneposzukiwańDrzewo binarne poszukiwań jestjest dynamiczną strukturą danych zbudowanądynamiczną strukturą danych zbudowaną zz węzłówwęzłów . Każdy węzeł może posiadać. Każdy węzeł może posiadać dwóch potomków (dwóch potomków (lewylewy ii prawyprawy) oraz) oraz jednegojednego przodkaprzodka. Z każdym węzłem. Z każdym węzłem dodatkowo związany jestdodatkowo związany jest kluczklucz..  Binarne drzewa wyszukiwań częstoBinarne drzewa wyszukiwań często stosuje się w zadaniach, w którychstosuje się w zadaniach, w których wymagane jest względnie szybkiewymagane jest względnie szybkie sortowanie lub wyszukiwanie elementów.sortowanie lub wyszukiwanie elementów.
  • 8.
    #include <stdlib.h>#include <stdlib.h> #include<stdio.h>#include <stdio.h> #include <string.h>#include <string.h> struct node{struct node{ int key;int key; struct node *lewy;struct node *lewy; struct node *prawy;struct node *prawy; }*korzen=NULL;}*korzen=NULL; void push(struct node *&korzen,int x)void push(struct node *&korzen,int x) {{ if(korzen==NULL)if(korzen==NULL) {{ korzen=(struct node*)malloc(sizeof(struct node));korzen=(struct node*)malloc(sizeof(struct node)); korzen->lewy=NULL;korzen->lewy=NULL; korzen->prawy=NULL;korzen->prawy=NULL; korzen->key=x;korzen->key=x; return;return; }else}else {{ if(x<(korzen->key))if(x<(korzen->key)) push(korzen->lewy,x);push(korzen->lewy,x); else push(korzen->prawy,x);else push(korzen->prawy,x); }} }} void showrek(struct node *korzen) //lewe poddrzewo,void showrek(struct node *korzen) //lewe poddrzewo, prawe,rekurencyjnieprawe,rekurencyjnie {{ if(korzen)if(korzen) {{ showrek(korzen->lewy);showrek(korzen->lewy); showrek(korzen->prawy);showrek(korzen->prawy); printf("%d ",korzen->key);printf("%d ",korzen->key); }} }} int main()int main() {{ int n,i,x;int n,i,x; printf("Ile elementow dodad do drzewa??n");printf("Ile elementow dodad do drzewa??n"); scanf("%d",&n);scanf("%d",&n); i=0;i=0; while(i!=n)while(i!=n) {{ printf("Element nr%d: ",i+1);printf("Element nr%d: ",i+1); scanf("%d",&x);scanf("%d",&x); push(korzen,x);push(korzen,x); i++;i++; }} showrek(korzen);showrek(korzen); system("PAUSE");system("PAUSE"); }}
  • 9.
     Drzewo przedziałoweDrzewoprzedziałowe, struktura danych, struktura danych przechowująca punkty, oraz związane z tymiprzechowująca punkty, oraz związane z tymi punktami wszystkie możliwe przedziały. Drzewopunktami wszystkie możliwe przedziały. Drzewo przedziałowe, jeśli jest skonstruowane tak, abyprzedziałowe, jeśli jest skonstruowane tak, aby było zrównoważone, pozwala odpowiadać nabyło zrównoważone, pozwala odpowiadać na zapytania o dowolny przedział w czasiezapytania o dowolny przedział w czasie logarytmicznym.logarytmicznym.
  • 10.
    #include <iostream>#include <iostream> usingnamespace std;using namespace std; const int MAXN = 1048576;const int MAXN = 1048576; int n, a[MAXN], intervalTree[2*MAXN];int n, a[MAXN], intervalTree[2*MAXN]; void read() {void read() { cin >> n;cin >> n; for(int i=0;i<n;i++) cin >> a[i];for(int i=0;i<n;i++) cin >> a[i]; }} void buildTree(int node) {void buildTree(int node) { if(node >= MAXN) { //sprawdzam czy node jest liściemif(node >= MAXN) { //sprawdzam czy node jest liściem intervalTree[node] = a[node-MAXN];intervalTree[node] = a[node-MAXN]; return; //zawracam, żeby nie wyjść poza zakres danychreturn; //zawracam, żeby nie wyjść poza zakres danych }} buildTree(node*2);buildTree(node*2); buildTree(node*2+1);buildTree(node*2+1); intervalTree[node] = intervalTree[node*2]+intervalTree[node*2+1]; //obliczamintervalTree[node] = intervalTree[node*2]+intervalTree[node*2+1]; //obliczam wartość w wierzchołku na podstawie synówwartość w wierzchołku na podstawie synów }} int query(int f, int s) { //query już jest iteracyjnyint query(int f, int s) { //query już jest iteracyjny f = f+MAXN; s = s+MAXN;f = f+MAXN; s = s+MAXN; if(f == s) return intervalTree[s];if(f == s) return intervalTree[s]; int res = intervalTree[f]+intervalTree[s];int res = intervalTree[f]+intervalTree[s]; while(f/2 != s/2) {while(f/2 != s/2) { if(f%2 == 0) res = res+intervalTree[f+1];if(f%2 == 0) res = res+intervalTree[f+1]; if(s%2 == 1) res = res+intervalTree[s-1];if(s%2 == 1) res = res+intervalTree[s-1]; f = f/2; s = s/2;f = f/2; s = s/2; }} return res;return res; void update(int f, int s) { //podstawiam a[f] := svoid update(int f, int s) { //podstawiam a[f] := s int restore = a[f-1];int restore = a[f-1]; a[f-1] = s;a[f-1] = s; f += MAXN-1;f += MAXN-1; while(f != 0) {while(f != 0) { intervalTree[f] += s-restore;intervalTree[f] += s-restore; f = f/2;f = f/2; }} }} int main() {int main() { read();read(); buildTree(1); //zaczynamy od korzenia i budujemybuildTree(1); //zaczynamy od korzenia i budujemy rekurencyjnierekurencyjnie while(1) {while(1) { char operationType; int f, s; //typ operacji: Q -char operationType; int f, s; //typ operacji: Q - zapytanie o sumę (f,s), U - zamienia a[f] na s, E - exitzapytanie o sumę (f,s), U - zamienia a[f] na s, E - exit cin >> operationType >> f >> s;cin >> operationType >> f >> s; if(operationType == 'Q') cout << query(f-1,s-1) <<if(operationType == 'Q') cout << query(f-1,s-1) << endl; //indeksuje od 0endl; //indeksuje od 0 if(operationType == 'U') update(f,s);if(operationType == 'U') update(f,s); if(operationType == 'E') return 0;if(operationType == 'E') return 0; }} return 0;return 0; }}