Skip to content
Snippets Groups Projects
Verified Commit 04dffc8b authored by orestis.malaspin's avatar orestis.malaspin
Browse files

updated 2025

parent 84abff70
No related branches found
No related tags found
No related merge requests found
Pipeline #38064 passed
---
title: "Fin des tables de hachages et arbres"
date: "2025-02-28"
---
# Rappel
* Qu'est-ce qu'une table de hachage?
. . .
* Structure de données abstraite où chaque *valeur* (ou élément) est associée à une *clé* (ou argument).
* Quelles sont les fonctions typiques définies sur les tables?
. . .
* Insetion, consultation, suppression.
```C
void insert(table, key, value)
value get(table, key)
value remove(table, key)
```
* Comment fait-on le lien entre une clé et une valeur dans le tableau?
. . .
* On hache!
# Exercice 2
* Reprendre l'exercice 1 et utiliser la technique de double hachage pour traiter
les collisions avec
\begin{align*}
h_1(k)&=k\mod 13,\\
h_2(k)&=1+(k\mod 11).
\end{align*}
* La fonction de hachage est donc $h(k)=(h(k)+h_2(k)) \% 13$ en cas de
collision.
# Exercice 3
* Stocker les numéros de téléphones internes d'une entreprise suivants dans un
tableau de 10 positions.
* Les numéros sont compris entre 100 et 299.
* Soit $N$ le numéro de téléphone, la fonction de hachage est
$$
h(N)=N\mod 10.
$$
* La fonction de gestion des collisions est
$$
C_1(N,i)=(h(N)+3\cdot i)\mod 10.
$$
* Placer 145, 167, 110, 175, 210, 215 (mettre son état à occupé).
* Supprimer 175 (rechercher 175, et mettre son état à supprimé).
* Rechercher 35.
* Les cases ni supprimées, ni occupées sont vides.
* Expliquer se qui se passe si on utilise?
$$
C_1(N,i)=(h(N)+5\cdot i)\mod 10.
$$
# Préambule
\small
* On considère pas le cas du chaînage en cas de collisions.
* L'insertion est construite avec une forme du type
```C
index = h(key);
while (table[index].state == OCCUPIED
&& table[index].key != key) {
index = (index + k) % table_size; // attention à pas dépasser
}
table[index].key = key;
table[index].state = OCCUPIED;
```
\normalsize
* Gestion de l'état d'une case *explicite*
```C
typedef enum {EMPTY, OCCUPIED, DELETED} state;
```
# L'insertion
## Pseudocode?
. . .
```C
rien insertion(table, clé, valeur) {
index = hash(clé)
index =
tant que état(table[index]) == occupé et clé(table[index]) != clé:
index = rehash(clé)
état(table[index]) = occupé
table[index] = valeur
}
```
# La suppression
## Pseudocode?
. . .
```C
valeur suppression(table, clé):
index = hash(clé)
tant que état(table[index]) != vide:
si état(table[index]) == occupé et clé(table[index]) == clé:
état(table[index]) = supprimé
sinon
index = rehash(clé)
}
```
# La recherche
## Pseudocode?
. . .
```C
booléen recherche(table, clé) {
index = hash(clé)
tant que état(table[index]) != vide:
si état(table[index]) == occupé et clé(table[index]) == clé:
retourner vrai
sinon
index = rehash
retourner faux
}
```
# Écrivons le code!
* Mais avant:
* Quelles sont les structures de données dont nous avons besoin?
* Y a-t-il des fonctions auxiliaires à écrire?
* Écrire les signatures des fonctions.
. . .
## Structures de données
\footnotesize
. . .
```C
typedef enum {empty, deleted, occupied};
typedef ... key_t;
typedef ... value_t;
typedef struct _cell_t {
key_t key;
value_t value;
state_t state;
} cell_t;
typedef struct _hm {
cell_t *table;
int capacity;
int size;
} hm;
```
# Écrivons le code!
## Fonctions auxiliaires
. . .
```C
static int hash(key_t key);
static int rehash(int index, key_t key);
static int find_index(hm h, key_t key);
```
## Signature de l'API
. . .
```C
void hm_init(hm *h, int capacity);
void hm_destroy(hm *h);
bool hm_set(hm *h, key_t key, value_t *value);
bool hm_get(hm h, key_t key, value_t *value);
bool hm_remove(hm *h, key_t key, value_t *value);
bool hm_search(hm h, key_t key);
void hm_print(hm h);
```
# Live code session!
0. Offered to you by ProtonVPN[^1]!
. . .
1. Like the video.
2. Subscribe to the channel.
3. Use our one time voucher for ProtonVPN: `PAULISAWESOME`.
4. Consider donating on our patreon.
[^1]: The fastest way to connect to BBB!
# Les arbres
\Huge Les arbres
# Les arbres: définition
"Un arbre est un graphe acyclique orienté possédant une unique racine, et tel que tous les nœuds sauf la racine ont un unique parent."
. . .
**Santé!**
## Plus sérieusement
* Ensemble de **nœuds** et d'**arêtes** (graphe),
* Les arêtes relient les nœuds entre eux, mais pas n'importe comment: chaque
nœud a au plus un **parent**,
* Le seul nœud sans parent est la **racine**,
* Chaque nœud a un nombre fini d'**enfants**,
* La hiérarchie des nœuds rend les arêtes **orientées** (parent -> enfants), et empêche les
**cycles** (acyclique, orienté).
* La **feuille** ou **nœud terminal** est un nœud sans enfants,
* Le **niveau** est 1 à la racine et **niveau+1** pour les enfants,
* Le **degré** d'un nœud est le nombre de enfants du nœud.
. . .
* Chaque nœud est un arbre en lui même.
* La **récursivité** sera très utile!
# Arbre ou pas arbre?
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
1-->2;
1-->3;
3-->2;
3-->4;
3-->5;
```
::::
. . .
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
1-->2;
1-->3;
3-->4;
3-->5;
3-->6;
```
::::
:::
# Arbre ou pas arbre?
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
1-->2;
1-->3;
3-->4;
3-->5;
3-->6;
6-->7;
7-->3;
```
::::
. . .
:::: column
```{.mermaid format=pdf width=300 loc=figs/}
graph TD;
1;
```
::::
:::
# Arbre ou pas arbre?
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
1---2;
1---3;
3---4;
3---5;
```
::::
. . .
:::: column
```{.mermaid format=pdf width=300 loc=figs/}
graph BT;
1-->2;
1-->3;
3-->4;
3-->5;
3-->6;
```
::::
:::
# Degré et niveau
* Illustration du degré (nombre d'enfants) et du niveau (profondeur)
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
1[degré 2]-->2[degré 0];
1-->3[degré 3];
3-->4[degré 0];
3-->5[degré 0];
3-->6[degré 0];
```
::::
. . .
:::: column
```{.mermaid format=pdf width=300 loc=figs/}
graph TD;
1[niveau 1]-->2[niveau 2];
1-->3[niveau 2];
3-->4[niveau 3];
3-->5[niveau 3];
3-->6[niveau 3];
```
::::
:::
* Les nœuds de degré 0, sont des feuilles.
# Application: recherche rapide
## Pouvez vous construire un arbre pour résoudre le nombre secret?
. . .
* Le nombre secret ou la recherche dichotomique (nombre entre 0 et 10).
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph LR;
5-->|<|2;
5-->|>|7;
7-->|>|8;
7-->|<|6;
8-->|>|9;
9-->|>|10;
2-->|<|1;
2-->|>|3;
3-->|>|4;
1-->|<|0;
```
::::
:::: column
**Question:** Quelle est la complexité pour trouver un nombre?
::::
:::
# Autres représentation
* Botanique
* **Exercice:** Ajouter les degrés/niveaux et feuilles
```{.mermaid width=250 format=pdf loc=figs/}
graph TD;
A-->B;
A-->C;
B-->D;
B-->E;
B-->F;
F-->I;
F-->J;
C-->G;
C-->H;
H-->K;
```
# Autres représentation
* Ensembliste
::: columns
:::: column
```{.mermaid width=300 format=pdf loc=figs/}
graph TD;
A-->B;
A-->C;
B-->D;
B-->E;
B-->F;
F-->I;
F-->J;
C-->G;
C-->H;
H-->K;
```
::::
. . .
:::: column
![](figs/ensemble.svg)
::::
:::
# Autres représentation
* Liste
::: columns
:::: column
```{.mermaid width=400 format=pdf loc=figs/}
graph TD;
A-->B;
A-->C;
B-->D;
B-->E;
B-->F;
F-->I;
F-->J;
C-->G;
C-->H;
H-->K;
```
::::
. . .
:::: column
```
(A
(B
(D)
(E)
(F
(I)
(J)
)
)
(C
(G)
(H
(K)
)
)
)
```
::::
:::
# Autres représentation
* Par niveau
::: columns
:::: column
```{.mermaid width=400 format=pdf loc=figs/}
graph TD;
A-->B;
A-->C;
B-->D;
B-->E;
B-->F;
F-->I;
F-->J;
C-->G;
C-->H;
H-->K;
```
::::
. . .
:::: column
```
1 2 3 4
-------------------------
A
B
D
E
F
I
J
C
G
H
K
```
::::
:::
# L'arbre binaire
* Structure de données abstraite,
* Chaque nœud a au plus deux enfants: gauche et droite,
* Chaque enfants est un arbre.
## Comment représenteriez vous une telle structure?
. . .
```C
<R, G, D>
R: racine
G: sous-arbre gauche
D: sous-arbre droite
```
## Comment cela s'écrirait en C?
. . .
```C
typedef struct _node {
contenu info;
struct _node *left, *right;
} node;
typedef node *tree;
```
# L'arbre binaire
## Que se passerait-il avec
```C
typedef struct _node {
int info;
struct _node left, right;
} node;
```
* On ne sait pas quelle est la taille de node, on ne peut pas l'allouer!
## Interface minimale
* Qu'y mettriez vous?
. . .
```C
NULL -> arbre (vide)
<n, arbre, arbre> -> arbre
visiter(arbre) -> nœud (la racine de l'arbre)
gauche(arbre) -> arbre (sous-arbre de gauche)
droite(arbre) -> arbre (sous-arbre de droite)
```
* Les autres opérations (insertion, parcours, etc) dépendent de ce qu'on stocke
dans l'arbre.
# Exemple d'arbre binaire
* Représentez `(c - a * b) * (d + e / f)` à l'aide d'un arbre binaire (matrix)
. . .
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
A[*]-->B[-];
B-->C[c];
B-->D[*];
D-->E[a];
D-->F[b];
A-->G[+];
G-->H[d];
G-->I["/"];
I-->J[e];
I-->K[f];
```
::::
:::: column
## Remarques
* L'arbre est **hétérogène**: le genre d'info est pas le même sur chaque nœud
(opérateur, opérande).
* Les feuilles contiennent les opérandes.
* Les nœuds internes contiennent les opérateurs.
::::
:::
# Parcours d'arbres binaires
* Appliquer une opération à tous les nœuds de l'arbre,
* Nécessité de **parcourir** l'arbre,
* Utiliser uniquement l'interface: visiter, gauche,
droite.
## Une idée de comment parcourir cet arbre?
* 3 parcours (R: Racine, G: sous-arbre gauche, D: sous-arbre droit):
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
A[*]-->B[-];
B-->C[c];
B-->D[*];
D-->E[a];
D-->F[b];
A-->G[+];
G-->H[d];
G-->I["/"];
I-->J[e];
I-->K[f];
```
::::
:::: column
1. Parcours **préfixe** (R, G, D),
2. Parcours **infixe** (G, R, D),
3. Parcours **postfixe** (G, D, R).
::::
:::
# Le parcours infixe (G, R, D)
* Gauche, Racine, Droite:
1. On descend dans l'arbre de gauche tant qu'il est pas vide,
2. On visite la racine du sous arbre,
3. On descend dans le sous-arbre de droite (s'il est pas vide),
4. On recommence.
. . .
## Incompréhensible?
* La récursivité c'est la vie.
```
parcours_infixe(arbre a)
si est_pas_vide(gauche(a))
parcours_infixe(gauche(a))
visiter(A)
si est_pas_vide(droite(A))
parcours_infixe(droite(A))
```
# Graphiquement (dessinons)
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
A[*]-->B[-];
B-->C[c];
B-->D[*];
D-->E[a];
D-->F[b];
A-->G[+];
G-->H[d];
G-->I["/"];
I-->J[e];
I-->K[f];
```
::::
:::: column
```
parcours_infixe(arbre a)
si est_pas_vide(gauche(a))
parcours_infixe(gauche(a))
visiter(A)
si est_pas_vide(droite(A))
parcours_infixe(droite(A))
```
::::
:::
# Graphiquement (`mermaid` c'est super)
::: columns
:::: column
```{.mermaid format=pdf width=400 loc=figs/}
graph TD;
A[*]-->B[-];
A[*]-.->|1|B[-];
B-->C[c];
B-.->|2|C[c];
C-.->|3|B;
B-->D[*];
B-.->|4|D;
D-->E[a];
D-.->|5|E;
E-.->|6|D;
D-->F[b];
D-.->|7|F;
F-.->|8|A;
A-->G[+];
A-.->|9|G;
G-->H[d];
G-.->|10|H;
H-.->|11|G;
G-->I["/"];
G-.->|12|I;
I-->J[e];
I-.->|13|J;
J-.->|14|I;
I-->K[f];
I-.->|15|K;
```
::::
:::: column
```
parcours_infixe(arbre a)
si est_pas_vide(gauche(a))
parcours_infixe(gauche(a))
visiter(A)
si est_pas_vide(droite(A))
parcours_infixe(droite(A))
```
## Remarque
Le nœud est visité à la **remontée**.
## Résultat
```
c - a * b * d + e / f
```
::::
:::
# Et en C?
## Live code
\footnotesize
. . .
```C
typedef int data;
typedef struct _node {
data info;
struct _node* left;
struct _node* right;
} node;
typedef node* tree_t;
void tree_print(tree_t tree, int n) {
if (NULL != tree) {
tree_print(tree->left, n+1);
for (int i = 0; i < n; i++) {
printf(" ");
}
printf("%d\n", tree->info);
tree_print(tree->right, n+1);
}
}
```
# Question
## Avez-vous compris le fonctionnement?
. . .
## Vous en êtes sûr·e·s?
. . .
## OK, alors deux exercices:
1. Écrire le pseudo-code pour le parcours R, G, D (matrix).
2. Écrire le pseudo-code pour la parcours G, D, R (matrix),
## Rappel
```
parcours_infixe(arbre a)
si est_pas_vide(gauche(a))
parcours_infixe(gauche(a))
visiter(A)
si est_pas_vide(droite(A))
parcours_infixe(droite(A))
```
# Correction
\footnotesize
* Les deux parcours sont des modifications **triviales**[^2] de l'algorithme
infixe.
## Le parcours postfixe
```python
parcours_postfixe(arbre a)
si est_pas_vide(gauche(a))
parcours_postfixe(gauche(a))
si est_pas_vide(droite(a))
parcours_postfixe(droite(a))
visiter(a)
```
## Le parcours préfixe
```python
parcours_préfixe(arbre a)
visiter(a)
si est_pas_vide(gauche(a))
parcours_préfixe(gauche(a))
si est_pas_vide(droite(a))
parcours_préfixe(droite(a))
```
. . .
**Attention:** L'implémentation de ces fonctions en C sont **à faire** en
exercice (inspirez vous de ce qu'on a fait avant)!
# Exercice: parcours
## Comment imprimer l'arbre ci-dessous?
```
f
/
e
+
d
*
c
-
b
*
a
```
. . .
## Bravo vous avez trouvé!
* Il s'agissait du parcours D, R, G.
# Implémentation
## Vous avez 5 min pour implémenter cette fonction et la poster sur matrix!
. . .
```C
void pretty_print(tree_t tree, int n) {
if (NULL != tree) {
pretty_print(tree->right, n+1);
for (int i = 0; i < n; ++i) {
printf(" ");
}
printf("%d\n", tree->info);
pretty_print(tree->left, n+1);
}
}
```
# Exercice supplémentaire (sans corrigé)
Écrire le code de la fonction
```C
int depth(tree_t t);
```
qui retourne la profondeur maximale d'un arbre.
Indice: la profondeur à chaque niveau peut-être calculée à partir du niveau des
sous-arbres de gauche et de droite.
# La recherche dans un arbre binaire
* Les arbres binaires peuvent retrouver une information très rapidement.
* À quelle complexité? À quelle condition?
. . .
## Condition
* Le contenu de l'arbre est **ordonné** (il y a une relation d'ordre (`<`, `>`
entre les éléments).
## Complexité
* La profondeur de l'arbre (ou le $\mathcal{O}(\log_2(N))$)
. . .
## Exemple: les arbres lexicographiques
* Chaque nœud contient une information de type ordonné, la **clé**,
* Par construction, pour chaque nœud $N$:
* Toutes clé du sous-arbre à gauche de $N$ sont inférieurs à la clé de $N$.
* Toutes clé du sous-arbre à droite de $N$ sont inférieurs à la clé de $N$.
# Algorithme de recherche
* Retourner le nœud si la clé est trouvée dans l'arbre.
```python
arbre recherche(clé, arbre)
tante_que est_non_vide(arbre)
si clé < clé(arbre)
arbre = gauche(arbre)
sinon si clé > clé(arbre)
arbre = droite(arbre)
sinon
retourne arbre
retourne NULL
```
# Algorithme de recherche, implémentation (live)
\footnotesize
. . .
```C
typedef int key_t;
typedef struct _node {
key_t key;
struct _node* left;
struct _node* right;
} node;
typedef node* tree_t;
tree_t search(key_t key, tree_t tree) {
tree_t current = tree;
while (NULL != current) {
if (current->key > X) {
current = current->gauche;
} else if (current->key < X){
current = current->droite;
} else {
return current;
}
}
return NULL;
}
```
# Exercice (5-10min)
Écrire le code de la fonction
```C
int tree_size(tree_t tree);
```
qui retourne le nombre total de nœuds d'un arbre et poster le résultat sur
matrix.
Indication: la taille, est 1 + le nombre de nœuds du sous-arbre de gauche
additionné au nombre de nœuds dans le sous-arbre de droite.
. . .
```C
int arbre_size(tree_t tree) {
if (NULL == tree) {
return 0;
} else {
return 1 + tree_size(tree->left)
+ tree_size(tree->right);
}
}
```
# L'insertion dans un arbre binaire
* C'est bien joli de pouvoir faire des parcours, recherches, mais si on peut
pas construire l'arbre....
## Pour un arbre lexicographique
* Rechercher la position dans l'arbre où insérer.
* Créer un nœud avec la clé et le rattacher à l'arbre.
# Exemple d'insertions
* Clés uniques pour simplifier.
* Insertion de 5, 15, 10, 25, 2, -5, 12, 14, 11.
* Rappel:
* Plus petit que la clé courante => gauche,
* Plus grand que la clé courante => droite.
* Faisons le dessins ensemble
```
```
## Exercice (3min, puis matrix)
* Dessiner l'arbre en insérant 20, 30, 60, 40, 10, 15, 25, -5
# Pseudo-code d'insertion (1/2)
* Deux parties:
* Recherche le parent où se passe l'insertion.
* Ajout de l'enfant dans l'arbre.
## Recherche du parent
```
arbre position(arbre, clé)
si est_non_vide(arbre)
si clé < clé(arbre)
suivant = gauche(arbre)
sinon
suivant = droite(arbre)
tant que clé(arbre) != clé && est_non_vide(suivant)
arbre = suivant
si clé < clé(arbre)
suivant = gauche(arbre)
sinon
suivant = droite(arbre)
retourne arbre
```
# Pseudo-code d'insertion (2/2)
* Deux parties:
* Recherche de la position.
* Ajout dans l'arbre.
## Ajout de l'enfant
```
ajout(arbre, clé)
si est_vide(arbre)
arbre = nœud(clé)
sinon
si clé < clé(arbre)
gauche(arbre) = nœud(clé)
sinon si clé > clé(arbre)
droite(arbre) = nœud(clé)
sinon
retourne
```
# Code d'insertion en C
## Recherche du parent (ensemble)
. . .
```C
tree_t position(tree_t tree, key_t key) {
tree_t current = tree;
if (NULL != current) {
tree_t subtree = key > current->key ? current->right :
current->left;
while (key != current->key && NULL != subtree) {
current = subtree;
subtree = key > current->key ? current->right :
current->left;
}
}
return current;
}
```
[^2]: Copyright cours de mathématiques pendant trop d'années.
<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<!-- Created with Inkscape (http://www.inkscape.org/) -->
<svg
width="265.59039mm"
height="182.94089mm"
viewBox="0 0 265.59039 182.94089"
version="1.1"
id="svg5"
inkscape:version="1.1.2 (0a00cf5339, 2022-02-04)"
sodipodi:docname="ensemble.svg"
xmlns:inkscape="http://www.inkscape.org/namespaces/inkscape"
xmlns:sodipodi="http://sodipodi.sourceforge.net/DTD/sodipodi-0.dtd"
xmlns="http://www.w3.org/2000/svg"
xmlns:svg="http://www.w3.org/2000/svg">
<sodipodi:namedview
id="namedview7"
pagecolor="#ffffff"
bordercolor="#666666"
borderopacity="1.0"
inkscape:pageshadow="2"
inkscape:pageopacity="0.0"
inkscape:pagecheckerboard="0"
inkscape:document-units="mm"
showgrid="false"
fit-margin-top="0"
fit-margin-left="0"
fit-margin-right="0"
fit-margin-bottom="0"
inkscape:zoom="0.28372389"
inkscape:cx="79.302451"
inkscape:cy="382.41404"
inkscape:window-width="1293"
inkscape:window-height="1022"
inkscape:window-x="14"
inkscape:window-y="44"
inkscape:window-maximized="1"
inkscape:current-layer="layer1" />
<defs
id="defs2" />
<g
inkscape:label="Layer 1"
inkscape:groupmode="layer"
id="layer1"
transform="translate(42.607488,92.780029)">
<g
id="g15861"
transform="translate(34.913169,-156.35674)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342"
cx="134.07271"
cy="173.43787"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="130.28389"
y="177.21611"
id="text5886"><tspan
sodipodi:role="line"
id="tspan5884"
style="stroke-width:0.264583"
x="130.28389"
y="177.21611">K</tspan></text>
</g>
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="82.876038"
y="-80.315704"
id="text7454"><tspan
sodipodi:role="line"
id="tspan7452"
style="stroke-width:0.264583"
x="82.876038"
y="-80.315704">A</tspan></text>
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="31.88768"
y="-43.87215"
id="text7898"><tspan
sodipodi:role="line"
id="tspan7896"
style="stroke-width:0.264583"
x="31.88768"
y="-43.87215">B</tspan></text>
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="153.94002"
y="-42.981239"
id="text8364"><tspan
sodipodi:role="line"
id="tspan8362"
style="stroke-width:0.264583"
x="153.94002"
y="-42.981239">C</tspan></text>
<g
id="g15881"
transform="translate(27.630306,-93.695044)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342-3"
cx="-30.602505"
cy="64.403992"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="-34.655907"
y="68.182236"
id="text9424"><tspan
sodipodi:role="line"
id="tspan9422"
style="stroke-width:0.264583"
x="-34.655907"
y="68.182236">D</tspan></text>
</g>
<g
id="g15886"
transform="translate(-17.328292,-87.382089)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342-5"
cx="9.5870228"
cy="93.993073"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="6.4490747"
y="97.771317"
id="text10528"><tspan
sodipodi:role="line"
id="tspan10526"
style="stroke-width:0.264583"
x="6.4490747"
y="97.771317">E</tspan></text>
</g>
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="48.897526"
y="-10.660181"
id="text11500"><tspan
sodipodi:role="line"
id="tspan11498"
style="stroke-width:0.264583"
x="48.897526"
y="-10.660181">F</tspan></text>
<g
id="g15876"
transform="translate(43.811753,-136.32377)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342-35"
cx="82.657463"
cy="126.26711"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="78.873932"
y="130.04535"
id="text12010"><tspan
sodipodi:role="line"
id="tspan12008"
style="stroke-width:0.264583"
x="78.873932"
y="130.04535">G</tspan></text>
</g>
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="161.13219"
y="-9.7197342"
id="text12520"><tspan
sodipodi:role="line"
id="tspan12518"
style="stroke-width:0.264583"
x="161.13219"
y="-9.7197342">H</tspan></text>
<g
id="g15871"
transform="translate(-74.105386,-114.48369)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342-7"
cx="112.37273"
cy="116.71143"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="110.58415"
y="120.48967"
id="text12920"><tspan
sodipodi:role="line"
id="tspan12918"
style="stroke-width:0.264583"
x="110.58415"
y="120.48967">I</tspan></text>
</g>
<g
id="g15866"
transform="translate(-11.45929,-129.96299)">
<circle
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.135684;stroke-opacity:1"
id="path4342-6"
cx="72.357376"
cy="143.44485"
r="7.5602813" />
<text
xml:space="preserve"
style="font-size:10.5833px;line-height:1.25;font-family:sans-serif;letter-spacing:0px;stroke-width:0.264583"
x="71.807045"
y="146.21768"
id="text14090"><tspan
sodipodi:role="line"
id="tspan14088"
style="stroke-width:0.264583"
x="71.807045"
y="146.21768">J</tspan></text>
</g>
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="path15910"
cx="90.187706"
cy="-1.3095872"
rx="132.6629"
ry="91.33815" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="path16014"
cx="29.470457"
cy="-6.0036306"
rx="53.721966"
ry="51.006378" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="path16014-6"
cx="154.85226"
cy="-4.0077286"
rx="53.721966"
ry="51.006378" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="path16340"
cx="49.329731"
cy="5.2435174"
rx="26.745842"
ry="26.28573" />
<ellipse
style="fill:none;fill-opacity:1;stroke:#000000;stroke-width:0.264583;stroke-opacity:1"
id="path16340-2"
cx="167.58054"
cy="4.8638148"
rx="26.745842"
ry="26.28573" />
</g>
</svg>
0% Loading or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment