Planche 1

Cours 1
Tri et recherche en table

Jean-Jacques.Levy@inria.fr
http://jeanjacqueslevy.net
tel: 01 39 63 56 89

secrétariat de l'enseignement:
Catherine Bensoussan
cb@lix.polytechnique.fr
Aile 00, LIX
tel: 01 69 33 34 67

http://www.enseignement.polytechnique.fr/informatique/


Planche 2

Plan

  1. Premier programme
  2. Rappels de Java
  3. Tri sélection
  4. Tri par insertions
  5. Recherche linéaire
  6. Hachage et listes de collisions
  7. Hachage à adressage ouvert

Planche 3

Premier programme

Programme qui affiche une chaîne et un entier.


class PremierProg {
    public static void main (String args[ ]){
        System.out.println ("Bonjour les forts!");
        System.out.println ("fib(20) = " + fib(20));
    }

    static int fib (int n) {
        if (n <= 1) return 1;
        else return fib (n-1) + fib (n-2);
    }
}
A mettre dans un fichier PremierProg.java, ensuite compiler


javac PremierProg.java
et exécuter le fichier PremierProg.class en lançant la JVM


java PremierProg

Planche 4

Types primitifs et Conversions

t est un type, e une expression et x un identificateur.
Planche 5

Instructions


Planche 6

Tableaux

Exercice 1Donner le sens de l'instruction a = b; quand a et b sont deux tableaux.


Planche 7

Fonctions

En Java, les fonctions sont aussi appelées méthodes car c'est la terminologie dans les langages orientés-objets. Nous utilisons les deux appelations.


class PremierProg {
    public static void main (String args[ ]){
       if (args.length != 1)
          System.out.println ("Mauvais nombre d'arguments.");
       else {
          int n = Integer.parseInt (args[0]);
          System.out.println (fib(n));
       }
    }

    static int fib (int n) {
        if (n <= 1) return 1;
        else return fib (n-1) + fib (n-2);
    }
}
La déclaration d'une fonction commence le type du résultat, puis vient le nom de la fonction et la déclaration des paramètres, et enfin on met le corps de la définition entre accolades.


Planche 8

Initialisation / Impression de tableaux


static int[ ] tableauAleatoire (int n) {
  int a[ ] = new int[n];
  for (int i = 0; i < a.length; ++i)
      a[i] = (int) (Math.random() * 100);
  return a;
}

static void imprimer (int[ ] a) {
  for (int i = 0; i < a.length; ++i)
    System.out.print(a[i] + " ");
  System.out.println();
}
Remarque: + est le seul opérateur surchargé de Java. Le sens de + est normal quand ses arguments sont numériques, mais dès qu'un de ses arguments est une chaîne de caractères, le 2ème argument est transformé en chaîne de manière naturelle et le résultat est la concaténation des deux chaînes de caractères.


Planche 9

Programme complet


class TableauIO {
    public static void main (String args[ ]){
       if (args.length != 1)
          System.out.println ("Mauvais nombre d'arguments.");
       else {
          int n = Integer.parseInt (args[0]);
          int[] a = tableauAleatoire (n);
          imprimer (a);
       }
    }

    static int[ ] tableauAleatoire (int n) {
      int a[ ] = new int[n];
      for (int i = 0; i < a.length; ++i)
          a[i] = (int) (Math.random() * 100);
      return a;
    }

    static void imprimer (int[ ] a) {
      for (int i = 0; i < a.length; ++i)
        System.out.print(a[i] + " ");
      System.out.println();
    }

}

Planche 10

Classes / Modularité


Planche 11

Visibilité des noms dans les classes


Planche 12

Objets


  class Date {
  
    int    j; // jour    
    int    m; // mois       
    int    a; // annee      
  }
  
  class BogueVirtuel {
    public static void main (String[ ] args) {
  
      Date an0 = new Date();
      an0.j = 1; an0.m = 1; an0.a= 1970;
  
      Date an2000 = new Date();
      an2000.j = 1; an2000.m = 1; an2000.a= 2000;
      
      System.out.println (an0.j + "/" + an0.m + "/" + an0.a);
      System.out.println (an2000.j + "/" + an2000.m + "/" + an2000.a);
    }
  }

Planche 13

Objets -- 2


Planche 14

Objets / Constructeurs

Exemple

class Date {
  int    j,  m,  a; 

  Date (int jour, int mois, int annee) {
    j = jour; m = mois; a = annee;
  }
      ...
      Date an0 = new Date (1, 1, 1970);
      Date an2000 = new Date (1, 1, 2000);
      ...
    }
}

Planche 15

Objets / Constructeurs / bis

Exemple revu

class Date {
  int    j,  m,  a; 

  Date (int jour, int mois, int annee) {
    this.j = jour; this.m = mois; this.a = annee;
  }
      ...
      Date an0 = new Date (1, 1, 1970);
      Date an2000 = new Date (1, 1, 2000);
      ...
En fait le constructeur commence implicitement par

    this = new Date();
et finit aussi implicitement par

    return this;

Planche 16

Objets / Champs statiques

Exemple

class Date {
  int    j,  m,  a; 
  static int instances = 0;

  Date (int jour, int mois, int annee) {
    j = jour; m = mois; a = annee; ++instances;
  }

  static Date an0 = new Date (1, 1, 1970);
  static Date an2000 = new Date (1, 1, 2000);
  static Date berlin = new Date (10, 11, 1989);
}

Planche 17

Exercice 2Que se passe-t-il si on oublie de mettre les attributs static pour les trois dernières dates?

Objets / Valeur

Exercice 3Si a et b sont deux dates, quel est le sens de l'affectation a = b; ?


Planche 18

Objets / Equals / toString

Deux méthodes (non statiques) utiles à définir dans une classe


class Date {
  ...  
  public boolean equals (Date d) {
    return j == d.j && m == d.m && a == d.a;
  }

  public String toString () {
    return j + "/" + m + "/" + a;
  }
}
Par convention, toString est appelé par + quand il a le sens de la concaténation des chaînes de caractères. De même pour System.out.print (x) qui équivaut à System.out.print (x + "") et donc à System.out.print (x.toString()).

On peut donc écrire
System.out.println (d) dans le cas des dates.


Planche 19

Arguments des méthodes non statiques

Comme pour les constructeurs, l'objet dont la méthode est un champ peut être précisé par le mot-clé
this.

On peut donc reprendre l'exemple précédent.


class Date {
  ...  
  public boolean equals (Date d) {
    return this.j == d.j && this.m == d.m && this.a == d.a;
  }

  public String toString () {
    return this.j + "/" + this.m + "/" + this.a;
  }

Planche 20

Grammaire BNF de Java (Backus Naur Form)

La grammaire de Java est complètement spécifiée, comme pour
~tous les langages de programmation.


ForStatement:
        for ( ForInitopt ; Expressionopt ; ForUpdateopt )
                Statement

ForInit:
        StatementExpressionList
        LocalVariableDeclaration

ForUpdate:
        StatementExpressionList

StatementExpressionList:
        StatementExpression
        StatementExpressionList , StatementExpression

Planche 21




StatementExpression:
        Assignment
        PreIncrementExpression
        PreDecrementExpression
        PostIncrementExpression
        PostDecrementExpression
        MethodInvocation
        ClassInstanceCreationExpression


Planche 22

Tri
et
Recherche en table

Planche 23

Recherche d'un minimum dans un tableau


static int minimum (int[ ] a) {
    r = Integer.MAX_VALUE;
    for (i=0; i < a.length; ++i)
        if ( a[i] < r )
            r = a[i];
    return r;
}
Ca marche pour le cas vide. (Il faut toujours y penser!).


Planche 24

Tri sélection

Donné: un tableau a de n éléments.

Résultat: le même tableau trié en ordre croissant, c'est à dire ai £ aj pour 0 £ i < j < n.

Algorithme:




Planche 25

Echange de deux éléments


  int x = 1, y = 2;

  int aux = x;
  x = y;
  y = aux;
Peut-on faire mieux?


Planche 26

Tri sélection -- le programme


static void triSelection (int[ ] a) {
    int   i_min, t;

    for (int i = 0; i < a.length - 1; ++i) {
        i_min = i;
        for (int j = i+1; j < a.length; ++j)
           if (a[j] < a[i_min])
               i_min = j; 
        t = a[i_min]; a[i_min] = a[i]; a[i] = t;
    }
}

Planche 27

Tri par insertions

Comme pour trier un paquet de cartes


static void triInsertion (int[ ] a) {
  int   j, v;

  for (int i = 1; i < a.length; ++i) {
      v = a[i]; j = i;
      while (j > 0  &&  a[j-1] > v) {
          a[j] = a[j-1]; 
          --j;
      }
      a[j] = v;
  }
}

Planche 28

Le tri Shell   [D. L. Shell 1959]


static void triShell (int[ ] a) {

  int h = 1; do h = 3*h + 1; while ( h <= a.length );
  do {
      h = h / 3;
      for (int i = h; i < a.length; ++i)
          if (a[i] < a[i-h]) {
              int   v = a[i], j = i;
              do {
                  a[j] = a[j-h];
                  j = j - h;
              } while (j >= h  &&  a[j-h] > v);
              a[j] = v;
          }
  } while ( h > 1);
}
Pas plus que O(n3/2) comparaisons !!
Bon pour de gros fichiers (celui du noyau Maple)



Planche 29

Recherche en table

Une table est une ensemble de paires
(k, d)k est une clé et d une donnée. Par exemple, k est un nom de personne, d est son numéro de téléphone (ou son adresse e-mail).

On cherche une clé dans une table pour obtenir la donnée correspondante.

Recherche séquentielle


static int recherche (String x, String[ ] nom, int[ ] tel) {

  for (int i = 0; i < nom.length; ++i)
      if (x.equals(nom[i]))
          return tel[i];
  return -1;
}

Planche 30

Recherche en table -- bis



Planche 31

Recherche dichotomique en table

On suppose la table ordonnée en ordre croissant.

=0ex

static int rechercheDichotomique (String x, String[ ] nom, int[ ] tel) {
  int   i, cmp, g = 0, d = nom.length-1;
  do {
      i = (g + d) / 2;
      cmp = x.compareTo(nom[i]);
      if (cmp == 0)
          return tel[i];
      if (cmp < 0)
          d = i - 1;
      else 
          g = i + 1;
  } while (g <= d);
  return -1;
}
Complexité O(log n).

Recherche par interpolation

Si distribution uniforme, interpolation linéaire de la clé recherchée. Complexité O(log(log n)).


Planche 32

Hachage -- Hashing


Planche 33

Hachage et collisions

Si
h(i)=h(j) ``par hasard'', que faire?
Plusieurs solutions :


Planche 34

Listes de collisions (listes d'association)


final static int M = 63, B = 128;

static Entree[] nom = new Entree[M];

static int rechercher (String x) {
  for (Entree e = nom[h(x)]; e != null; e = e.suivant)
    if (x.equals(e.cle))
      return e.tel;
  return -1;
}
static void inserer (String x, int t) {
  int i = h(x);
  nom[i] = ajouter (x, t, nom[i]); 
}
static Entree ajouter (String x, int t, Entree e) {
  if (e == null) 
    return new Entree (x, t, null);
  else {
    e.suivant = ajouter (x, t, e.suivant);
    return e;
  }
}

Planche 35

Hachage par Adressage ouvert

On range directement les entrées dans le tableau, et en cas de collision on fait une bête recherche linéaire. Il faut pouvoir borner le nombre maximum d'entrées. On utilise une valeur spéciale pour repérer les cases libres.

static int rechercher (String x) {

  for (int  i = h(x); !nom[i].equals (""); i = (i+1) % M)
    if (x.equals(nom[i]))
      return tel[i];
  return -1;
}

static void inserer (String x, int t) {

  int i = h(x);
  while (!nom[i].equals ("")) 
    i = (i+1) % M;
  nom[i] = x; tel[i] = t;
}

Planche 36

Adressage ouvert -- bis

La complexité ne dépend que du taux d'occupation
a=n/m, et vaut:

1/2(1+1/1-a2) 10cmpour une insertion ou recherche avec échec,
1/2(1+1/1-a) pour une recherche avec succès.

Pour a=66%, on fait 5 et 2.
Pour
a=90%, on fait 50 et 5.

Pour accélerer on peut faire un double hachage, en augmentant
i de u=h2(x), où h2 est une seconde fonction de hachage, au lieu du pas de 1.

On fait alors
1/1 - a et 1/a ln (1/1-a).

Pour
a = 80%, 5 et 1,3;
Pour
a = 99%, 100 et 5.
Planche 37

Hachage multiple


Planche 38



Exercice 4Calculer la complexité moyenne de la recherche avec hachage simple dans le cas d'une recherche avec succès et avec échec.

Exercice 5Si on insère les nouvelles entrées en tête de la liste de collisions plutôt qu'à la fin, cela change-t-il le coût moyen?

Exercice 6Calculer la complexité du tri par insertions.

Exercice 7(plus difficile) Montrer les formules de complexité de la recherche avec succès et échec du hachage avec adressage ouvert.

Renseignements sur Java

Aller voir les pages Web en:

http://www.enseignement.polytechnique.fr/local/documentation/
.../documentation/java/jdk1.1.7/docs/
.../documentation/java/jdk1.1.7/docs/api/packages.html


This document was translated from LATEX by HEVEA.