Récursivité dans l'algorithmique et la programmation/Structure de données récursives

De testwiki
Aller à la navigation Aller à la recherche

Modèle:Chapitre

La structure de donnée récursive est monnaie courante dans l'informatique de tous les jours; elle apparaît dès que l’on parle de liste, file, arbre, graphe, ... Peu de langages de programmation n'en permettent pas l'utilisation, que ce soit explicitement par l'intermédiaire de pointeurs, ou implicitement par des références. Nous nous bornerons ici à en décrire succinctement le principe, et à en présenter les plus courantes.

Principe

La plupart des langages permettent de créer de nouveaux types de données qui sont la réunion de plusieurs autres types de données (struct en C/C++, record en Pascal, classes pour les langages objets, ...). Rendre un type auto référant, consiste simplement à créer un type T et à le munir d'au moins un membre dont le type sera T. Évidemment, tout comme pour les algorithmes, le cas où un type T contient un membre de type S, et que ce dernier contient un membre de type T est englobé par le définition. La représentation classique d'une instance de ce type est formalisée par

donne´es 

La partie données est l'information maintenue par ce type, la case blanche représente une référence vers ce même type et la flèche indique que cette référence est utilisée et pointe vers l'instance concernée. Si la référence ne pointe pas vers une instance alors cela est formalisé ainsi :

donne´es 

Une telle instance indique une terminaison (fin de la liste, feuille d'un arbre)

Chat ||Chien ||

Représente une instance d'un type agrégeant une chaîne de caractères, trois références. Cette instance contient contient la chaîne de caractères Chat. Les deux premières références ne sont pas utilisées, on dit que leur valeur est nulle, elles ne pointent nulle part. La dernière référence pointe vers une instance du même type contenant la chaîne de caractère Chien. L'ordre des références est en général important.

Les listes chaînées

Chaînage simple

Les listes simplement chaînées permettent de représenter des listes d'éléments quelconques.

type_ noeud=structure_m1 : type1mn : typensuivant : noeudfstructure_type_ liste  =structure_tete : noeudfstructure_

Une instance particulière appelée tête de liste est une référence sur le premier élément de la liste. La liste d'entiers (5, 2, 17, 8) pourrait être représentée ainsi :

Tete5 2 17 8 

On dispose entre autres des fonctions d'accès suivantes pour écrire nos algorithmes : cree´r_listecre´e une liste initialement vide (i.e. Tete est nulle)cree´r_noeud( valeur, suivant )initialise un nouveau noeudajouter_tete( liste, noeud )ajoute noeud en te^te de listeajouter_queue( liste, noeud )ajoute noeud en fin de listeeffacer_tete( liste )efface la te^te de listeeffacer_queue( liste )efface la queue de listesuivant( noeud )renvoie le noeud suivant

Chaînage double

Si dans la définition du nœud on ajoute une référence precedent, avec la contrainte que pour un nœud N qui n'est ni la tête ni la queue suivant(precedent(N))=precedent(suivant(N))=N, alors on obtient une liste doublement chaînée. Elle peut se parcourir aussi bien de la tête vers la queue que dans l'autre sens.

type_ noeud=structure_m1 : type1mn : typensuivant : noeudprecedent : noeudfstructure_type_ listechainagedouble  =structure_tete : noeudfstructure_


Tete5  2  17  8

Pile, file, etc.

Les piles et les files sont simplement des listes simplement ou doublement chaînées, seules leurs fonctions d'accès diffèrent. En ce qui concerne la pile, on peut uniquement empiler (ajouter en tête), et dépiler (récupération de la valeur de tête, destruction de celle-ci). Quant à la file, on peut seulement enfiler (ajouter en tête) et défiler (récupération de la valeur de queue, destruction de celui-ci). Parmi les implémentations particulières de listes, on pourra citer, les ensembles (chaque valeur est présente une et une seule fois dans la liste), les listes de hashage, les matrices creuses.

Remarques

Les listes apportent un comportement dynamique qui fait parfois défaut aux tableaux. Les tableaux de dimension supérieure à 1 peuvent avantageusement être remplacés par des listes de listes.

Les arbres

Les arbres binaires

Un arbre binaire représente une structure hiérarchique, comme un arbre généalogique. Le nœud de l'arbre est composé de deux références (tout comme un nœud de liste doublement chaînée), on les nomme souvent FG pour fils gauche et FD pour fils droit. Il faut voir ces liens comme un chemin que l’on emprunte à partir de la racine jusqu'à un nœud. La seule contrainte à propos de ce chemin est qu’il ne doit en exister qu'un à partir de la racine vers un nœud quelconque.

type_ noeud=structure_m1 : type1mn : typenFG : noeudFD : noeudfstructure_type_ arbre  =structure_racine : noeudfstructure_

On définit des propriétés telles que le degré d'un nœud (nombre de reférences utilisées, i.e. n'ayant pas une valeur nulle), la hauteur d'un arbre (nombre maximum de descendants), le niveau d'un nœud (distance le séparant de la racine). Un nœud de degré 0 est appelé feuille, un nœud de degré supérieur à 0 est appelé nœud interne.

Modèle:Exemple

Arbres n-aires

Un arbre qui est composé de nœuds pouvant avoir au maximum n références est dit arbre n-aire. On le retrouve dans l'arborescence du disque dur, par exemple. Un arbre unaire est une liste, on dit qu’il a dégénéré en liste. Tout arbre n-aire peut être transformé en arbre binaire.

Graphes

Si l’on construit une structure avec un nombre quelconque de références, sans contraintes particulières (cycle, connexité, ...) alors on obtient un graphe. Un exemple courant de graphe est une carte routière où les villes sont les nœuds et les routes les références. Les graphes sont des outils d'une puissance extraordinaire, mais leur maîtrise est complexe (mais pas compliqué).

Modèle:Bas de page