10d. Gebalanceerde zoekbomen
2021-03-12
slides.com/jod/pt_10d
Docent: Jo Devriendt
Assistent: Ann Philips
Coördinator: Joost Vennekens
voornaam.achternaam@kuleuven.be
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Analyse van
complete zoekboom
- n = #nodes
-
Om element toe te voegen, te vinden of te verwijderen, loop je in het slechtste geval over de hoogte van de boom
- #stappen = hoogte
- hoogte
- #stappen = O(log(n))
- volgorde blijft behouden
- Beter dan lineaire datastructuren waar een element vinden O(n) stappen kost
6
4
8
5
2
7
9
3
1
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Probleem: geen garantie dat zoekboom compleet is...
#define N 5
int main() {
int waardes[N] = {0,1,2,3,4};
printf("Bouw zoekboom\n");
Node* root = NULL;
for (int i = 0; i < N; ++i) {
root = voegToe(root, waardes[i]);
}
print(root, 0);
root = destroy(root);
}
$ ./a.out
Bouw zoekboom
->4
->3
->2
->1
->0
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Tussenoplossing:
gebalanceerde zoekboom
- Gebalanceerd: voor elke node, de linker- en rechtersubboom verschillen niet meer dan 1 in hoogte
- Elke complete boom is gebalanceerd
- Een gebalanceerde boom met n nodes heeft
hoogte = O(log(n))
6
4
8
5
2
7
9
3
1
Verschillende hoogte linker- en rechterdeelboom
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
#define N 5
int main() {
int waardes[N] = {0,1,2,3,4};
printf("Bouw zoekboom\n");
Node* root = NULL;
for (int i = 0; i < N; ++i) {
root = voegToe(root, waardes[i]);
}
print(root, 0);
root = destroy(root);
}
$ ./a.out
Bouw zoekboom
->4
->3
->2
->1
->0
Probleem: geen garantie dat zoekboom gebalanceerd is...
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
balanceer
-
Stockeer waarden gesorteerd in dynamische array
- Bvb. mbv. Stack :)
- Merk op: inorder loopt van klein naar groot door boom
- Creëer nieuwe boom recursief
- neem middelste waarde voor huidige node
- creëer linkerdeelboom met kleinere waarden
- creëer rechterdeelboom met grotere waarden
Node* balanceer(Node* t);
void toStack(Node* t, Stack* s);
Node* maak(int waardes[], int lengte);
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
balanceer
6
4
8
2
7
9
3
1
maak
4
[1]
[6]
2
7
[3]
[8,9]
4
maak
[1,2,3]
[6,7,8,9]
toStack
[1,2,3,4,6,7,8,9]
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
balanceer
4
[1]
[6]
2
7
[3]
[8,9]
[]
[]
maak
4
2
7
3
1
6
8
9
maak
4
2
7
3
1
6
8
9
maak
4
2
7
[]
[]
[]
[]
[]
[]
[]
[9]
1
3
6
8
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
balanceer
void toStack(Node* t, Stack* s) {
if (t == NULL) {
return;
}
toStack(t->links, s);
push(s, t->data);
toStack(t->rechts, s);
}
Node* balanceer(Node* t) {
Stack s = create();
toStack(t, &s);
t = destroy(t);
t = maak(s.waardes, s.lengte);
destroyStack(&s);
return t;
}
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
balanceer
Node* maak(int waardes[], int lengte) {
if (lengte == 0) {
return NULL;
}
Node* p = (Node*) malloc(sizeof(Node));
int mid = lengte / 2;
p->data = waardes[mid];
p->links = maak(&waardes[0], mid);
p->rechts = maak(&waardes[mid + 1], lengte - (mid + 1));
return p;
}
Node* balanceer(Node* t) {
Stack s = create();
toStack(t, &s);
t = destroy(t);
t = maak(s.waardes, s.lengte);
destroyStack(&s);
return t;
}
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
#define N 11
int main() {
int waardes[N] = {5,8,4,10,3,1,6,7,9,0,2};
printf("Bouw zoekboom\n");
Node* root = NULL;
for (int i = 0; i < N; ++i) {
root = voegToe(root, waardes[i]);
}
print(root, 0);
printf("Balanceer zoekboom\n");
root = balanceer(root);
print(root, 0);
root = destroy(root);
}
Bouw zoekboom
->10
->9
->8
->7
->6
->5
->4
->3
->2
->1
->0
Balanceer zoekboom
->10
->9
->8
->7
->6
->5
->4
->3
->2
->1
->0
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Hoe zoekboom gebalanceerd houden?
- Een verwijder / voegToe operatie kan de zoekboom uit balans brengen
- balanceer(...) is O(n)
- telkens balanceer oproepen is te kostelijk
-
Zelf-balancerende zoekbomen
- AVR-bomen, rood-zwart bomen, ...
- verwijder / voegToe aangepast zodat de boom in balans blijft, in O(log(n))
- details brengen ons te ver :)
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Oefening
- Schrijf een procedure maakCompleet die van een willekeurige zoekboom een complete zoekboom maakt.
Node* maakCompleet(Node*);
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Samenvatting
- Gebalanceerde zoekbomen laten toe om in O(log(n)) op te zoeken, toe te voegen, te verwijderen
- Zelf-balancerende bomen zorgen dat zoekboom gebalanceerd blijft tijdens manipulatie
10d. Gebalanceerde zoekbomen
By Jo Devriendt
10d. Gebalanceerde zoekbomen
- 603