Slides:



Advertisements
Présentations similaires
Mais vous comprenez qu’il s’agit d’une « tromperie ».
Advertisements

La recherche de chemin optimal
CHAPITRE 8 LES ALIMENTS 3/25/2017 Des fruits Madame Craven.
Structures de données avancées : B arbres
Structures de données avancées : Principales structures de données
Tris.
Chapitre 3 Les arbres binaires
Fonctions & procédures
Calculs de complexité d'algorithmes
Cours MIAGE « Architectures Orientées Services » Henry Boccon-Gibod 1 Orchestration de Web Services Module 5 Exercice Pratique à l'usage de l'environnement.
1 UMLV 1. Introduction 2. Hachage ouvert 3. Hachage fermé 4. Implémentation des fonctions Méthodes de hachage.
Algorithme et structure de données
Chap. 1 Structures séquentielles : listes linéaires
Chapitre VI. Arbres (définition, parcours, représentation)
Traitement Co-Séquentiel: Appariment et Fusion de Plusieurs Listes
Utilisation des tableaux
Chapitre IV. Structures linéaires (piles, files, listes chaînées)
Cours 8 Arbres équilibrés
ALGORITHMES RECURSIFS
Cours 7 - Les pointeurs, l'allocation dynamique, les listes chaînées
Structures de données linéaires
Cours d’Algorithmique
LOGO Responsable du cours Mlle Amina GHRAB : 1 ère année IAG Institut Supérieur de Gestion de Tunis.
Les structures de données arborescentes
Arbre binaire de recherche
Les algorithmes: complexité et notation asymptotique
IFT-2000: Structures de Données
Chapitre VII. Tri Tri par tas Tri rapide.
RECURSIVITE ARBRES BINAIRES
Arbre Rouge Noir.
Les tris.
Gestion de Fichiers Arbres B.
Les fichiers indexés (Les B-arbres)
LA STRUCTURE D'ARBRE-B Institut National des Sciences Appliquées – Rouen Département Architecture des Systèmes d’Information.
LES ARBRES IUP 2 Génie Informatique
Arbres Rouge noir Démo : INF3105 Structures de données et algorithmes
Structures de données IFT-2000
Gestion de Fichiers Indexes basés sur les structures d’arbres binaires et indexes à niveaux multiples.

Les arbres et tas binomiaux
Gestion de Fichiers GF-10: Traitement Co-Sequentiel: Appariment et Fusion de Plusieures Listes (Base sur les sections de Folk, Zoellick & Riccardi,
Exposé en structures de données

Aire d’une figure par encadrement
Algorithmique et structures de données en C
Structures de données IFT-2000
LES ARBRES Un arbre est une structure homogène dont chaque élément,
Structures de données IFT-2000 Abder Alikacem Semaine 11 Gestion des arbres binaires de tri et de recherche. Les arbres cousus. Les arbres n-aires Département.
Structures de données IFT-2000 Abder Alikacem Retour sur les listes ordonnées Département dinformatique et de génie logiciel Édition Septembre 2009.
201 UMLV  Type « dictionnaire » sous-ensembles finis de E (ordonné) avec les opérations : Ens_vide :  Ens Ajouter : Ens x Elément  Ens Enlever.
Le langage C Structures de données
Ch. PAUL - Piles et Files à l'aide de listes chainées
ALGORITHMIQUE Recherches : Tris : séquentielle, dichotomique
LES PILES ET FILES.
Prolog Listes Arbres en prolog Structures : bases de données
Chapitre 6 Les traitements avancés
Pr ZEGOUR DJAMEL EDDINE Ecole Supérieure d’Informatique (ESI)
Méthodes de tri.
Arbres binaires et tables de hachage
Structures de données avancées : B arbres
1 UMLV  FICHIERS Mémoire de masse découpée en blocs Fichier :liste chaînée de blocs, ou arbre de blocs (répertoires - fichiers)‏ Bloc d’éléments Bloc.
Algorithmes de tri.
Structures de données IFT-2000
Structures de données IFT-2000
Structures de données IFT-2000 Abder Alikacem Semaine 10 Les algorithmes de recherche Les structures arborescentes Département d’informatique et de génie.
Les monceaux (Heap) Monceaux Propriétés des Monceaux
4/25/2017 4:30 PM Arbres (2,4) CSI2510 CSI2510.
CSI25101 Tri Plus efficace. CSI25102 Tri récursif Le tri récursif divise les données de grande taille en deux presque moitiés et est appelé récursivement.
. Le B-Arbre.
1. Tri rapide ou Quicksort Principe : La méthode du Quicksort due au C.A. Hoare (1962) utilise les principes généraux de division et équilibrage. 2.
Transcription de la présentation:

Arbres racine noeud interne père fils droit fils gauche feuilles Un arbre est soit un arbre atomique (une feuille), soit un noeud et une suite de sous-arbres. racine noeud interne père fils droit fils gauche feuilles L'ensemble des noeuds est constitué des nœuds internes et des feuilles

L’intérêt de cette organisation est de laisser à l’utilisateur le soin de regrouper les fichiers à sa convenance tout en maintenant une structure hiérarchique.

Représentation symbolique des arbres Arbre vide Arbre singleton Arbre quelconque Arbre binaire CECI N'EST PAS UN ARBRE deux pères

Par définition un arbre est une structure de données constituée d’un nœud appelé racine et de sous-arbres fils de la racine. C’est donc une définition récursive. racine Un nœud peut contenir une ou plusieurs valeurs, et on parlera alors d'arbres étiquetés et de la valeur (ou des valeurs) d'un nœud.

 x Les caractéristiques d’un arbre sont :         La taille de l’arbre est le nombre total de nœuds.         La hauteur ou niveau d’un nœud x est le nombre de liens sur l’unique chemin allant de la racine à x, notée h(x).      La hauteur ou profondeur de l’arbre A, h(A) = max { h(x) }  x racine x

hauteur d'un nœud dans un arbre de racine r: si x = r h(x) = 0 sinon h(x) = 1 + h(père(x)) La profondeur d'un nœud est la longueur du chemin qui le joint à la racine. La racine est de hauteur 0, ses fils de hauteur 1 et les k autres nœuds de hauteur supérieure à 1. La longueur de cheminement de l’arbre A, LC(A) =  h(x) x

profondeur # noeuds # feuilles Exemple de mesures profondeur # noeuds # feuilles 0 1 0 1 2 0 2 3 2 3 1 0 4 2 1 5 1 0 6 2 2 LC(A) =  h(x) x h = 6 Taille = 12 Nbrf = 5

Arbres binaires a d g b b f c d a c e g e arbre équilibré f La différence entre la hauteur du sous-arbre gauche et la hauteur du sous-arbre droit est d'au plus une unité. La recherche d'une clé d'un côté sera plus lente qu'une recherche de l'autre côté.

Arbre binaire typedef struct cellule { int data; struct noeud *fils_gauche;  struct noeud *fils_droit;  } nœud;

elt arbre nouveau_binaire(int elt, arbre racine) { • Un Arbre est un pointeur sur un nœud, la racine de l’arbre : typedef nœud *arbre; • Un Arbre vide est un pointeur NULL : arbre = NULL;   • Nouveau : il faut faire une allocation mémoire et placer l’étiquette. En cas d’erreur d’allocation le pointeur renvoyé est NULL (l’arbre est vide) : arbre nouveau_binaire(int elt, arbre racine) { racine = (nœud *) malloc(sizeof (nœud )); if (racine != NULL)){ racinedata = elt; racine fils_gauche= NULL; racine fils_droit=NULL; } return(racine); elt NULL NULL

Il faut relier un noeud à un ou plusieurs sous arbres. arbre cons_binaire(arbre racine, arbre s_arb_g, arbre s_arb_d) { racine fils_gauche = s_arb_g; racine fils_droit = s_arb_d; return(racine); }

Hauteur int HauteurArbre(arbre A) { if(A non vide) return (1 + Max(HauteurArbre(Ag), HauteurArbre(Ad)) ); else return 0; } Complexité : O(n) Nombre noeud int NbrNoeud(arbre A) { if(A non vide) return (1 + NbrNoeud(Ag) + NbrNoeud(Ad) ); else return 0; }

Max noeud int MaxNoeud(arbre A) { if(A non vide) return Max(data, MaxNoeud(Ag), MaxNoeud(Ad)); else return 0; } Min noeud int MinNoeud(arbre A) { if(A non vide) return Min(data, MinNoeud (Ag), MinNoeud (Ad)) ; else return 0; }

Arbre binaire de recherche ABR Utilisation importante en Info pour la localisation, +, -, tri … Un arbre binaire de recherche est un arbre binaire tel que pour tout nœud x , les nœuds de son sous arbre-gauche s’ils en existent ont des valeurs inférieures ou égales à celle de x, et les nœuds de son sous arbre-droit des valeurs strictement supérieures. X <=X >X Ce que l’on traduit par g(A)  racine(A) < d(A). 24 10 37

r Ag Ad <= r > r Un arbre binaire est soit vide, noté Ø, soit de la forme < r, Ag, Ad > où r est la racine et où Ag et Ad sont des arbres binaires.

Ag Ad Tout sous-arbre d’un ABR est un ABR 24 29 16 8 20 27 35 1 15 Exemple d’arbre binaire de recherche

Complexité : O(2n+1) * O(1) = O(n) test si arbre binaire et de recherche bool TestABR(arbre T){ if(T non vide){ if( TestABR(Td) est un ABR && TestABR(Tg) est un ABR) { if((Td pas vide) && (Tddata <= Tdata)) return (probleme) else { if((Tg pas vide) && (Tgdata > Tdata)) else return (OK) } return (???) racine x Tg Td <= x > x Complexité : O(2n+1) * O(1) = O(n)

Parcours en profondeur d'un arbre binaire de recherche 12 Parcours en profondeur d'un arbre binaire de recherche 9 23 -2 10 22 78 -77 9 On considère l’opération de parcours d’un arbre binaire qui consiste à examiner systématiquement dans un certain ordre tous les nœuds de l’arbres pour effectuer un traitement de données.

Parcours préfixe Parcours préfixe : 12, 9, -2, -77, 9, 10, 23, 22, 78 Lister Père Prefixe(Fils_G) Prefixe(Fils_autres) 9 23 -2 10 22 78 void Prefixe(arbre racine) { if (! vide(racine)) { printf(“%d\t”,racinedata); Prefixe(racinefils_gauche); Prefixe(racinefils_droit); } -77 9 Le parcours en profondeur à gauche consiste à partir de la racine et à tourner autour de l’arbre en allant toujours le plus à gauche possible. Parcours préfixe : 12, 9, -2, -77, 9, 10, 23, 22, 78

Parcours infixe III I II 12 Infixe(Fils_G) Lister Père Infixe(Fils_autres) 9 23 -2 10 22 78 void infixe(arbre racine) { if (! vide(racine)) { infixe(racinefils_gauche); printf(“%d\t”,racinedata); infixe(racinefils_droit); } -77 9 infixe : -77, -2, 9, 9, 10, 12, 22, 23, 78 SI ABR Le parcours infixe affiche les éléments dans l’ordre croissant.

Parcours suffixe ou Postfixe II I III 12 9 23 -2 10 22 78 -77 9 void Postfixe(arbre racine) { if (! vide(racine)) { Postfixe(racinefils_gauche); Postfixe(racinefils_droit); printf(“%d\t”,racinedata); } Parcours Postfixe : -77, 9, -2, 10, 9, 22, 78, 23, 12

Exemple: Parcours 3 5 1 4 6 2 Parcours préfixe : 3, 1, 0, 2, 5, 4, 6 2 Infixe(Fils_G) Lister Père Infixe(Fils_autres) Parcours infixe : 0, 1, 2, 3, 4, 5, 6 Posfixe(Fils_G) Posfixe(Fils_autres) Lister Père Parcours postfixe : 0, 2, 1, 4, 6, 5, 3

Exemple: Parcours 1 2 3 4 5 6 7 Parcours préfixe : Infixe(Fils_G) Lister Père Infixe(Fils_autres) Parcours infixe : Posfixe(Fils_G) Posfixe(Fils_autres) Lister Père Parcours postfixe :

Recherche d’un élément  Recherche dichotomoque rechercher : valeur x dans arbre == Rech(x,arbre)  booléen   On compare l’élément à la valeur de la racine : -   si le sous-arbre sélectionné est vide, l’élément est absent  échec rechercher ( x ,  ) = faux -   si égalité  succès x = r  rechercher (x ,<r , g , d > ) = vraie 24 29 35 16 27 20 3 5 1 -   si la valeur est plus petite, on recommence récursivement dans le sous-arbre gauche ; et réciproquement si la valeur est plus grande dans le sous-arbre droit x < r  rechercher (x , < r , g , d > ) = rechercher (x , g ) x > r  rechercher (x , < r , g , d > ) = rechercher (x , d )   Complexité : La complexité au pire est en O ( hauteur de l’arbre ).

Soit à rechercher 20 dans l'arbre suivant 24 20 est plus petit que 24 20 est plus grand que 16 29 16 20 est trouvé 3 20 27 35 1 5

Adjonction d’un élément aux feuilles L’adjonction aux feuilles d’un élément se réalise en deux étapes : -          étape de recherche pour savoir où insérer le nouvel élément ; -          adjonction elle-même. arbre ajout_feuille (arbre A, int e )  { if (A==  ) return < e ,  ,  > else if ( e  racine(A) ) return < racine(A) , ajout_feuille( g(A) , e ) , d(A) > else return < racine(A) ,g(A) , ajout_feuille( d(A) , e ) > } e La complexité d’une adjonction est O ( h(A) ).

x arbre insert(arbre T, int x) { if(T vide) { //sommet vide T = (struct nœud *) malloc(sizeof(struct nœud)) Tdata = x Tdroit = NULL Tgauche = NULL }else{ //sommet non vide if(Tdata == x) //ne rien faire !! else { if(x < Tdata) //inserer ds arbre gauche Tg = insert(Tg, x) else //inserer ds arbre droit Td = insert(Td, x) } return T NULL x

mais pas la complexité de la programmation !!! La complexité d’un ajout est O ( h(A) ). Alors que l’insertion dans un tableau nécessite de déterminer sa place, en parcourant le tableau depuis le début (k comparaisons) puis de décaler les (n-k) éléments successeurs pour ménager une place. Donc une complexité en O(n) avec n le nombre d’éléments du tableau. ABR  réduire la complexité en temps mais pas la complexité de la programmation !!!

remplace le nœud par son fils Suppression d’un élément arbre supprimer (arbre , valeur)  arbre recherche de l’élément à supprimer suppression qui dépend de la place de l’élément soit on remplace le nœud à supprimer par le plus grand élément de son sous-arbre gauche, soit on le remplace par le plus petit élément de son sous-arbre droit. immédiate noeud avec deux fils nœud avec un seul fils nœud sans fils remplace le nœud par son fils

arbre suppression ( arbre A , int e ) { if (A== ) // recherche de l’élément à supprimer return erreur; if ( e < racine(A) ) return < racine(A), suppression( g(A) , e ) , d(A) ); else if ( e > racine(A) ) return < racine(A), g(A) , suppression( d(A) , e ) ); else { // on l’a trouver donc suppression if est_feuille(A) return (  ); else if (g(A) == ) return d(A); else if (d(A) ==  ) return g(A); else { // on ajoute l’élément le plus à droite du sous-arbre gauche retourner < max_noeud(g(A)) , retire_max(g(A)), d(A) > }

La complexité est O ( h(A) ). int max_noeud ( arbre A) { // retourne le plus grand élément de l’arbre A, le plus à droite if ( d(A) == ) return racine(A); else return max_noeud(d(A)) ; } // retourne l’arbre privé de son plus grand élément arbre retire_max ( arbre A ) { if ( d(A) == ) return g(A); else return < racine(A) , g(A) , retire_ max(d(A)) >; } La complexité est O ( h(A) ).

La structure de tas La structure de tas est un arbre vérifiant les deux propriétés suivantes: L’arbre est un arbre binaire parfait La valeur de tout nœud est >= à celle de ses descendants Arbres binaires complets Un arbre binaire est complet si tous les nœuds qui ne sont pas des feuilles ont 2 fils. 15 14 2 8 13 7 5

Arbres binaires parfaits, ordre hiérarchique Un arbre binaire est parfait si toutes ses feuilles sont situées sur les deux derniers niveaux, l’avant dernier étant complet, et les feuilles du dernier sont le plus à gauche possible. Attention ! un arbre binaire parfait n’est pas forcément complet. tas 15 14 2 8 13

Tas = arbre binaire parfait partiellement ordonné ¨ arbre parfait: – toutes les feuilles sont sur les deux derniers niveaux, – l'avant dernier niveau est complet – les feuilles du dernier niveau sont le plus à gauche possible ¨ partiellement ordonné: – tout nœud est plus grand que ses deux fils 24 23 7 16 1 22 10 8 5 4

Tests !! Arbres binaires complets 15 14 2 Arbre binaire complet ? 8 7 Un arbre binaire est complet si tous les nœuds qui ne sont pas des feuilles ont 2 fils. 15 14 2 Arbre binaire complet ? 8 7 5

Tests !! Arbres binaires complets 15 9 14 2 8 13 Un arbre binaire est complet si tous les nœuds qui ne sont pas des feuilles ont 2 fils. 15 9 14 2 8 13 Arbre binaire complet ? 7 5

Tests !! Arbres binaires parfaits, ordre hiérarchique Un arbre binaire est parfait si toutes ses feuilles sont situées sur les deux derniers niveaux, l’avant dernier étant complet, et les feuilles du dernier sont le plus à gauche possible. Attention ! un arbre binaire parfait n’est pas forcément complet. 15 14 2 8 13 7 5 Arbre binaire parfait? Arbre binaire complet ?

 = 2h+1 - 1 La structure de tas N <=  Racine = + gd valeur Profondeur ou Nbr nœuds Niveau Max 0 20 = 1 1 21 = 2 2 22 = 4 h=3 au Max 23 = 8 24 16 23 8 10 22 7 1 5 Exemple de tas  = 2h+1 - 1 N <=

Profondeur ou Nbr nœuds Niveau Max 0 20 = 1 1 21 = 2 Index Profondeur ou Nbr nœuds Niveau Max 0 20 = 1 1 21 = 2 2 22 = 4 3 au Max 23 = 8 1 2 3 2*2=4 5 6 2*3+1=7 8 9 10 24 16 23 8 10 22 7 1 5 4 Exemple de tas Index 2*Index 2*Index + 1 Nœud x en i, son père est en i/2 Nœud x en i, son fils gauche en 2*i Nœud x en i, son fils droit en 2*i+1

Relation entre un tas et tableau int pere(i){ return (i/2); }   int gauche(i){ return (2 * i); int droit(i){ return (2 * i + 1); Relation entre un tas et tableau Index 1 2 3 2*2=4 5 6 2*3+1=7 8 9 10 24 16 23 8 10 22 7 1 5 4 i 1 2 3 4 5 6 7 8 9 10 24 16 23 8 10 22 7 1 5 4 tab[i]

Insertion d’un élément dans un tas Opérations sur les tas Insertion d’un élément dans un tas 24 24 23 7 16 1 22 8 5 4 10 16 23 8 10 22 7 22 1 5 4 Nouveau nœud insérer le plus à gauche possible sur le niveau de profondeur le plus élevée.  tjr arbre binaire complet mais pas forcement un tas.

Insertion de n éléments  O(nlogn) 1 2 3 4 5 6 7 8 9 10 11 24 24 16 23 22 23 8 22 22 7 8 16 22 7 1 5 4 10 1 5 4 10 tant que ( y  racine ) et ( y > père(y) ) faire échanger y et père(y) Compléxité : O(h) avec h : hauteur du tas Or la hauteur d’un tas de taille n = log2n  l’insertion requiert un temps O(logn) Insertion de n éléments  O(nlogn)

VERIFICATION void ajouter (int tab[], int ntas , int val ) { // ajoute l’élément x au tas de ntas éléments int i; ntas ++ ; i =ntas ; tab[i] = val ; while ( ( i > 1 ) && ( tab[i/2] < tab[i] ) ){ Echanger ( tab[i], tab[i / 2] ); i = i/2 ; } VERIFICATION

Echanger i = i/2  i=11/2=5 Avant l’ajout i 1 2 3 4 5 6 7 8 9 10 22 + 11 24 16 23 8 10 22 7 1 5 4 tab[i] 24 16 23 7 1 22 8 5 4 tab[i] 10 Echanger i = i/2  i=5/2=2 24 22 23 7 1 16 8 5 4 tab[i] 10 while ( tab[i /2] < tab[i ] ) { Echanger ( tab[i], tab[i / 2] ); i = i/2 ; }

i 1 2 3 4 5 6 7 8 9 10 11 24 22 23 8 16 22 7 1 5 4 10 tab[i] 1 2 3 4 5 6 7 8 9 10 11 24 22 23 CQFD 8 16 22 7 10 1 5 4

Exce : Construction d’un tas 8 15 2 13 14 5 3 tab[i] 15 8 2 13 tas + + 8 15 15 8 15 8 2 tas 15 13 2 8 + 15 13 2 8 14 tas 15 14 2 8 13 + tas 15 14 5 8 13 2 3

i 1 2 3 4 5 6 7 8 15 2 13 14 5 3 tab[i] int i; ntas ++ ; i =ntas ; tab[i] = val ; while ( ( i > 1 ) && ( tab[i/2] < tab[i] ) ){ Echanger ( tab[i], tab[i / 2] ); i = i/2 ; } 8 15 15 8 tab[2/2] < tab[2] 8 15 2 3 5 14 13 tab[i] i 1 2 3 4 5 6 7 8 15 2 3 5 14 13 tab[i] 13 15 2 3 5 14 8 13 15 2 3 5 14 8 14 15 2 3 5 13 8

int i; ntas ++ ; i =ntas ; tab[i] = val ; while ( ( i > 1 ) && ( tab[i/2] < tab[i] ) ){ Echanger ( tab[i], tab[i / 2] ); i = i/2 ; } i 1 2 3 4 5 6 7 tab[i] 15 14 2 8 13 5 3 14 15 5 3 2 13 8 14 15 5 3 2 13 8 14 15 5 3 2 13 8

Suppression d’un élément On remplace la valeur du nœud par celle du nœud le plus à droite possible sur le niveau de profondeur le plus élevée, nœud que l’on supprime alors, puis permutations. Exp: racine : suppression du premier élément de la file 24 4 16 23 16 23 8 10 22 7 8 10 22 7 1 5 4 1 5 4

4 23 4 7 16 1 22 10 8 5 16 23 8 10 22 7 23 22 7 16 1 4 10 8 5 1 5

Tri par tas [Heap sort] 15 14 5 8 13 2 3 3 14 5 8 13 2 15 Suppression Principe : deux phases -   Construire un tas contenant les n éléments par adjonction successives ; en O (n log n). -   Tant que le tas n’est pas vide, répéter l'opération de prendre l'élément de la racine (max), le retirer du tas avec réorganisation, mettre ce max à sa place définitive  ; en O (n log n). 15 14 5 8 13 2 3 3 14 5 8 13 2 15 Suppression réorganisation

réorganisation 14 13 5 8 3 2 15 3 14 5 8 13 2 15 2 13 5 8 3 14 15 Suppression

trier_tas(A) { construire_tas(A) while( …) echanger A[1] avec A[taille] supprimer A[taille] taille = taille – 1 reorganisation() }

1: construction d’un tas Test !!! i 1 2 3 4 5 6 7 3 5 14 13 2 15 8 tab[i] 1: construction d’un tas 2: ajout de 20

Test !!! 15 20 15 14 13 2 5 8 3 13 14 5 8 3 2 20 15 13 14 3 2 5 8 20 + i 1 2 3 4 5 6 7

5, 1, 7, 3, 4, 6, 2 Test !!! Construction d’un arbre binaire de recherche (ABR). r i 1 2 3 4 5 6 7 Ag Ad 5, 1, 7, 3, 4, 6, 2 <= r > r Prefixe, Infixe , Postfixe ??

Application : Imprimante en réseau User1 FIFO Tri: Arbre JbU1 JbUn JbU1 JbUn User2 UserN JbU5 JbU1 JbUn

Diviser pour régner Existe-t-il une méthode pour rechercher une récursivité et évaluer a priori sa complexité? On peut couper un problème de taille N en A problèmes identiques Recomposition de ces A problèmes se fait en un temps d'ordre N

Exemple : TRI par FUSION Pour trier un tableau t de n éléments, on le scinde en deux tableaux de même taille (à un élément près). On les note t1 de taille n1 et t2 de taille n-n1. Ces deux tableaux sont ensuite triés (appel récursif) et enfin fusionnés de manière à reformer le tableau t trié. tableau t scinder scinder scinder T(N) = 2 * T(N/2) + ordre N d'où T(N) = N log2N fusionner fusionner fusionner

Quicksort : tri rapide Principe : ‘’ diviser pour régner ‘’ On prend un élément au hasard dans le tableau à trier. Soit p (pivot) sa valeur. On partitionne le reste du tableau en 2 zones: les éléments plus petits ou égaux à p, et les éléments plus grands à p. Si on arrive à mettre en tête du tableau les plus petits que p et en fin du tableau les plus grands, on peut mettre p entre les deux zones à sa place définitive. On recommence récursivement la procédure Quicksort sur chacune des partitions tant qu'elles ne sont pas réduites à un élément. A la fin, la liste est triée par ordre croissant. p > pivot  pivot g > pivotG  pivotG d > pivotD  pivotD

p > pivot  pivot g d void Quicksort ( int tab[] , int g , int d ) { // Quicksort ( tab , 0 , n ) int k; //position du pivot if( g < d){ Placer (tab , g , d , &k); Quicksort (tab , g , k - 1); Quicksort (tab, k + 1 , d); }

La partition et le placement du pivot ne nécessitent qu’un parcours. La fonction Placer : La partition et le placement du pivot ne nécessitent qu’un parcours. p  p > p x K j+1 i L j On utilise deux compteurs L et K qui partent des extrémités du sous-tableau, et qui vont l’un vers l’autre : -   L part de i+1 et avance tant que l’on rencontre un élément  à p. -   K part de j et recule tant que l’on rencontre un élément > à p. On échange les deux éléments et on recommence la progression jusqu’à ce que les deux compteurs se croisent : la place définitive du pivot est en k, et on y place le pivot p par échange avec un élément  à p. complexité en moyenne O (n log n).

Exemple de tri rapide 5 3 2 6 4 1 7 i j 5 3 2 6 4 1 7 3 2 6 4 1 7 3 2 4 1 6 7 5 3 2 4 1 6 7

Arbres balancés ou B-arbres Les B_arbres sont des arbres de recherche équilibrés conçus pour être efficaces sur des disques ou d'autres unités de stockage secondaire à accès direct. Dans une application classique ayant recours aux B_arbres, la quantité de données gérées est si grande qu’elles ne tiennent pas toutes en même temps dans la mémoire principale. prendre en compte la taille des blocs disques regrouper les nœuds voisins dans un même bloc Généralisation des ABR

Éclatement d'une racine

Éviter de ‘’ réinventer la roue ‘’ Jeu de l'urne Soient -         B boules blanches et N boules noires dans une urne. -         B  0, N  0, B+N  1 -         Une réserve infinie de boules   Mode de fonctionnement   Tirage aveugle de 2 boules -         si les boules sont de même couleur, on remet une boule noire dans l'urne -         sinon, on remet une boule blanche Le jeu se termine lorsqu'il ne reste plus qu'une boule dans l'urne Question Quelle est la couleur de la dernière boule connaissant les nombres initiaux N et B?

Le jeu se terminera-t-il ou pas? Tirage aveugle de 2 boules -  si les boules sont de même couleur, on remet une boule noire dans l'urne -  sinon, on remet une boule blanche Le jeu se terminera car à chaque tirage, le nombre de boules dans l'urne diminue de 1.

GENERALISER RESOLUTION : Exemple avec 3 Boules: 2Bles de même couleur  N sinon, on remet  boule blanche RESOLUTION : Le jeu se terminera car à chaque tirage, le nombre de boules dans l'urne diminue de 1. Exemple avec 3 Boules: GENERALISER

GENERALISER !! Impensable

Tirages possibles et propriétés? AUTRE APPROCHE : Tirages possibles et propriétés? (B-2) + (N+1) B + (N-1) B + (N-1) Conclusion   La parité des blanches est inchangée. Donc, si le nombre initial B est impair, la dernière boule sera blanche, sinon, elle sera noire.