10c. Zoekbomen
2021-03-12
slides.com/jod/pt_10c
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
Zoekboom
- Datastructuur in de vorm van een binaire boom om gegevens gesorteerd te stockeren
- Voor elke node:
- Linkse descendants bevatten strikt kleinere waarden
- Rechtse descendants bevatten strikt grotere waarden
5
4
2
1
8
typedef struct node {
int data;
struct node* links;
struct node* rechts;
} Node;
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
destroy
Node* destroy(Node* t) {
if (t != NULL) {
destroy(t->links);
destroy(t->rechts);
free(t);
}
return NULL;
}
typedef struct node {
int data;
struct node* links;
struct node* rechts;
} Node;
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
voegToe(&2,3)
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
voegToe(&2,3)
voegToe(&4,3)
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
voegToe(&2,3)
voegToe(&4,3)
voegToe(NULL,3)
3
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
voegToe(&2,3)
voegToe(&4,3)
3
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
voegToe(&2,3)
3
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
2
1
4
Voeg 3 toe aan deze boom:
3
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
voegToe
Node* voegToe(Node* t, int x) {
if (t == NULL) {
Node* nieuw = (Node*) malloc(sizeof(Node));
nieuw->data = x;
nieuw->links = NULL;
nieuw->rechts = NULL;
return nieuw;
}
if (x < t->data) {
t->links = voegToe(t->links, x);
} else if (x > t->data) {
t->rechts = voegToe(t->rechts, x);
}
return t;
}
Werkt meteen ook om een initiële boom aan te maken ("create"):
Node* root = voegToe(NULL,...);
typedef struct node{
int data;
struct node* links;
struct node* rechts;
} Node
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
print & main
void print(Node* t, int level) {
if (t == NULL) {
return;
}
print(t->rechts, level + 1);
for (int i = 0; i < 4 * level; ++i) {
printf(" ");
}
printf("->");
printf("%-2d\n", t->data);
print(t->links, level + 1);
}
#define N 11
int main() {
int waardes[N] = {5,8,4,10,3,1,6,7,9,0,2};
Node* root = NULL;
for (int i = 0; i < N; ++i) {
root = voegToe(root, waardes[i]);
}
print(root, 0);
root = destroy(root);
}
$./a.out
->10
->9
->8
->7
->6
->5
->4
->3
->2
->1
->0
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Complex: zoekboom moet gesorteerd blijven
- x zit niet in de boom: doe niks
- node met x heeft minstens 1 NULL kind: verwijder node met x, ander kind wordt kind van ouder
- node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
- meest rechtse node bestaat niet: rechterkind (==NULL) van linkerkind vervangen door rechterkind van huidige node, verwijder huidige node
Node* verwijder(Node* t, int x);
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
2. node met x heeft minstens 1 NULL kind: verwijder node met x, ander kind wordt kind van ouder
Node* verwijder(Node* t, int x);
2
1
4
3
Verwijder 4:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
2. node met x heeft minstens 1 NULL kind: verwijder node met x, ander kind wordt kind van ouder
Node* verwijder(Node* t, int x);
2
1
3
Verwijder 4:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
2. node met x heeft minstens 1 NULL kind: verwijder node met x, ander kind wordt kind van ouder
Node* verwijder(Node* t, int x);
2
1
3
Verwijder 4:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
Node* verwijder(Node* t, int x);
4
1
5
2
Verwijder 4:
3
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
3
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
Verwijder 4:
4
1
5
2
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
3
1
5
3
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
Verwijder 4:
2
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
3
1
5
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
Verwijder 4:
2
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
3
1
5
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat: waarde van die node wordt waarde van huidige node, verwijder die node, maar behoud diens linkerkind
Verwijder 4:
2
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat niet: rechterkind (==NULL) van linkerkind vervangen door rechterkind van huidige node, verwijder huidige node
Node* verwijder(Node* t, int x);
Verwijder 2:
2
1
4
0
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
2
1
4
0
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat niet: rechterkind (==NULL) van linkerkind vervangen door rechterkind van huidige node, verwijder huidige node
Verwijder 2:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
2
1
4
0
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat niet: rechterkind (==NULL) van linkerkind vervangen door rechterkind van huidige node, verwijder huidige node
Verwijder 2:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
verwijder
Node* verwijder(Node* t, int x);
1
4
0
3. node met x heeft geen NULL kinderen: zoek meest rechtse node van linker deelboom
- meest rechtse node bestaat niet: rechterkind (==NULL) van linkerkind vervangen door rechterkind van huidige node, verwijder huidige node
Verwijder 2:
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Node* verwijder(Node* t, int x) {
if (t == NULL) {
// x komt blijkbaar niet voor
return NULL;
}
if (x < t->data) {
t->links = verwijder(t->links, x);
return t;
} else if (x > t->data) {
t->rechts = verwijder(t->rechts, x);
return t;
}
// x == t->data
if (t->links == NULL) {
Node* p = t->rechts;
free(t);
return p;
} else if (t->rechts == NULL) {
Node* p = t->links;
free(t);
return p;
}
// vervolg: twee niet-NULL deelbomen
// ...
x komt niet voor
Zoek verder
Minstens 1 NULL kind
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Node* verwijder(Node* t, int x) {
// vervolg: twee niet-NULL deelbomen
Node* p = t->links;
Node* q = t;
while (p->rechts != NULL) {
q = p;
p = p->rechts;
}
if (q != t) { // wel meest rechtse node
q->rechts = p->links;
t->data = p->data;
free(p);
return t;
} else { // geen meest rechtse node
p->rechts = t->rechts;
free(t);
return p;
}
}
Vind meest rechtse node in linkerdeelboom
Behoud linkerkind
Kopieer waarde
Verwijder meest rechtse
Verwijder huidige node
Vervang NULL-kleinkind
Geef linkerkind terug
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("Verwijder 5 & 8\n");
root = verwijder(root, 5);
root = verwijder(root, 8);
print(root, 0);
root = destroy(root);
}
Bouw zoekboom
->10
->9
->8
->7
->6
->5
->4
->3
->2
->1
->0
Verwijder 5 & 8
->10
->9
->7
->6
->4
->3
->2
->1
->0
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Oefeningen
Schrijf procedures voor
- bevat: test of een waarde in de boom zit
- max: geeft de grootste waarde in de boom terug
int bevat(Node* t, int x);
int max(Node* t);
Programmeertechnieken [B-KUL-YI0855]
De Nayer, IIW, E-ICT, 2Ba + schakel, 2020-2021
Samenvatting
-
Zoekbomen zijn een niet-lineaire datastructuur voor gesorteerde data
- links zitten kleinere elementen
- rechts grotere
- Manipulatie van zoekboom vereist enigszins complexe algoritmes
10c. Zoekbomen
By Jo Devriendt
10c. Zoekbomen
- 628