IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

C# Discussion :

L’algorithme d'Huffman en c# !


Sujet :

C#

  1. #1
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 96
    Points : 48
    Points
    48
    Par défaut L’algorithme d'Huffman en c# !
    Bonjour les loulous,

    Je suis actuellement en train de me pencher sur l'algorithme d'Huffman en C#, langage que je ne maîtrise pas encore... (Il faut bien un début à tout !)

    Je l'ai déjà fait en C, et j'aimerai refaire un peu la même chose en C#, juste pour connaître les différences entre les deux langages.

    Je suis face à un problème que je n'arrive pas à résoudre. Pour ceux qui ne connaisse pas, l'algorithme d'Huffman est là : http://fr.wikipedia.org/wiki/Codage_de_Huffman

    J'essaye de compresser des fichiers textes. Ce qui fait que je compte le nombre d’occurrence de mes lettres, et je les places comme suis :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    A	1
    l	1
    l	2
    e	1
    r	1
     	1
    l	3
    e	2
    s	1
     	2
    m	1
    e	3
    c	1
    s	2
     	3
    o	1
    n	1
     	4
    y	1
     	5
    c	2
    r	2
    o	2
    i	1
    t	1
     	6
    !	1
    Maintenant, j'aimerai créer une liste, pour ensuite l'utiliser et créer un arbre avec celle ci. (Cas d'école me voilà !)

    Je fais ceci :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
     
    	struct Maillon
    	{
    		char octet;
    		int occurence;
    		struct Maillon * filsGauche;
    		struct Maillon * filsDroit;
    		struct Maillon * suivant;
    	}
    Mais d'après mes quelques recherches, je ne peux pas utiliser de pointeurs dans une structure et sur une structure, à cause du Garbage collector.

    Donc, je vous demande ici même, puis je utiliser les pointeurs ? Ou, sinon, comment puis je pallier au problème ?

    Merci à tous =)

    Sylvanocry.

  2. #2
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    En C#, tu n'utilises pas les pointeurs (ou du moins très très rarement) explicitement.
    Ca donne:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    class Maillon
    	{
    		char octet;
    		int occurence;
    		Maillon filsGauche;
    		Maillon filsDroit;
    		Maillon suivant;
    	}

  3. #3
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par Sylvanocry Voir le message
    Donc, je vous demande ici même, puis je utiliser les pointeurs ?
    Tu peux, mais seulement dans un contexte "unsafe". Et de toutes façons ce n'est pas du tout comme ça qu'on fait habituellement en C#. L'utilisation des pointeurs se limite à quelques usages très spécifiques, par exemple quand le code C# doit interagir avec du code natif.

    Citation Envoyé par Sylvanocry Voir le message
    Ou, sinon, comment puis je pallier au problème ?
    Déjà, déclare Maillon comme une classe plutôt que comme une structure, sinon tu ne pourras pas les "imbriquer" comme tu fais.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    	class Maillon
    	{
    		public char octet;
    		public int occurence;
    		public Maillon filsGauche;
    		public Maillon filsDroit;
    		public Maillon suivant;
    	}
    Changements par rapport à ton code d'origine :

    - ajout du modificateur public sur les champs (sinon c'est private par défaut). Soit dit en passant : en général, en C# on évite d'exposer publiquement des champs ; on met les champs en privé et on utilise des propriétés pour y accéder (un propriété est en fait une paire de méthodes get/set). Mais pour que ça reste simple, j'ai juste mis public, sinon ça fait beaucoup de choses à la fois à assimiler...

    - les membres filsGauche, filsDroit et suivant ne sont plus déclarés comme des pointeurs : ce sont en fait des références. En C#, toutes les variables dont le type est un "type référence" (class) contiennent en fait une référence qui pointe vers l'objet sur le tas. Cette référence peut éventuellement être "null", c'est à dire qu'elle ne pointe vers aucun objet. Par opposition, les variables de "type valeur" (struct) contiennent directement la valeur.

    Sinon, je ne connais pas l'algo en question, mais octet représente-t-il réellement un octet, ou un caractère ? En C on considère souvent que c'est la même chose, mais en C# ce n'est pas pareil. Il y a un type byte (octet) et un type char (charactère unicode). A toi de voir ce qui convient le mieux selon le besoin...

  4. #4
    Expert confirmé

    Homme Profil pro
    Chef de projet NTIC
    Inscrit en
    Septembre 2006
    Messages
    3 580
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Haute Garonne (Midi Pyrénées)

    Informations professionnelles :
    Activité : Chef de projet NTIC
    Secteur : Aéronautique - Marine - Espace - Armement

    Informations forums :
    Inscription : Septembre 2006
    Messages : 3 580
    Points : 5 194
    Points
    5 194
    Par défaut
    sinon, si tu as la flemme :

    Huffman en C#

  5. #5
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 96
    Points : 48
    Points
    48
    Par défaut
    Bonjour à vous deux,

    D'une part merci beaucoup pour ces explications. Cela va m'aider à avancer de façon plus structurée.

    J'ai donc mis mon ancienne structure de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
        class Maillon
        {
            public char octet;
            public int occurence;
            public Maillon filsGauche;
            public Maillon filsDroit;
            public Maillon suivant;
        }
    Maintenant que tout est un peu plus claire, je me penche sur mes anciennes fonctions...
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
              int liste_longueur(Maillon l)
            {
     
                Maillon courant = null;
                int taille = 0;
                courant = l;
     
                while (courant != null)
                {
                    taille++;
                    courant = courant->suiv;
                }
     
                return taille;
            }
    Les pointeurs en C, c'était rigolo

    Je vous fais par de la suite des évènements d'ici peu.

  6. #6
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    L'opérateur -> ne s'utilise qu'avec les pointeurs (comme en C d'ailleurs)
    Utilise le point à la place

  7. #7
    Membre du Club
    Profil pro
    Étudiant
    Inscrit en
    Avril 2009
    Messages
    96
    Détails du profil
    Informations personnelles :
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : Étudiant

    Informations forums :
    Inscription : Avril 2009
    Messages : 96
    Points : 48
    Points
    48
    Par défaut
    Re bonjour.

    Pour l'instant j'ai fait ces petits fichier là : (et j'en suis pas peu fier. (oui j'ai un certain égo à satisfaire.))

    Ce fichier, Form.cs me permet de lire un fichier texte, et de compter les occurrences de lettres.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    using System;
    using System.Collections.Generic;
    using System.ComponentModel;
    using System.Data;
    using System.Drawing;
    using System.Linq;
    using System.Text;
    using System.Windows.Forms;
    using System.IO;
     
     
    namespace Algo_de_huffman
    {
        public partial class Form1 : Form
        {
            private char[]   BufDeLettre ;
            public Liste liste;
     
            public Form1()
            {
                InitializeComponent();
            }
     
            private void m_buttonComp_Click(object sender, EventArgs e)
            {
                if (textBox1.Text == "")
                {
                    MessageBox.Show("Entrer un fichier text !");
                }
                else
                    lectureFichier(textBox1.Text);
            }
     
            public void lectureFichier(string fichier)
            {
                string line;
                DataGridViewColumn col = new DataGridViewTextBoxColumn();
                DataGridViewColumn col1 = new DataGridViewTextBoxColumn();
                col.Name = "Caractère";
                this.dataGridView1.Columns.Add(col);
     
     
                col1.Name = "Occurence";
                this.dataGridView1.Columns.Add(col1);
     
                DataGridViewRowCollection rows = this.dataGridView1.Rows;
     
                System.IO.StreamReader file = new System.IO.StreamReader(fichier);
                BufDeLettre = new char[256];
     
                textBox2.Text = file.ReadToEnd();
                file.BaseStream.Position = 0;
                while ((line = file.ReadLine()) != null)
                {
                    for (int i = 0 ; i < line.Length; i++)
                    {
                        BufDeLettre[line[i]]++;
                        rows.Add(line[i], (int)BufDeLettre[line[i]]);
                    }
                }
     
                file.Close();
     
            }
     
        }
    }
    J'ai ce petit affichage fort sympathique :

    Maintenant que mon tableau est fait, et que mes occurrences de lettres comptées, j'aimerai utiliser ce fichier pour créer une liste de maillon (un maillon représenté par une valeur, un maillon suivant, et la lettre qu'il représente (pour l'instant) ).

    Je m'y suis pris de cette façon :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    22
    23
    24
    25
    26
    27
    28
    29
    30
    31
    32
    33
    34
    35
    36
    37
    38
    39
    40
    41
    42
    43
    44
    45
    46
    47
    48
    49
    50
    51
    52
    53
    54
    55
    56
    57
    58
    59
    60
    61
    62
    63
    64
    65
    66
    67
    68
    69
    70
    71
    72
    73
    74
    75
    76
    77
    78
    79
    80
    81
    82
    83
    84
    85
    86
    87
    88
    89
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Text;
     
    namespace Algo_de_huffman
    {
     
        class Liste
        {
            public char val;
           // public int occurence;
           // public Maillon filsGauche;
           // public Maillon filsDroit;
            public Liste suivant;
     
            Liste liste_creer()
            {
                return null;
            }
     
     
            // Cette fonction peut s'écrire de cette façon :         
            // return l ? liste_longueur(l->suiv) +1 : 0 ;
            int liste_longueur(Liste l)
            {
     
                Liste courant = null;
                int taille = 0;
                courant = l;
     
                while (courant != null)
                {
                    taille++;
                    courant = courant.suivant;
                }
     
                return taille;
            }
     
     
     
            Liste liste_nieme(Liste l, int indice)
    	    {
                Liste adresse;
                int indice_courant = 0;
     
                for (adresse = l; adresse != null; adresse = adresse.suivant)
                {
                    if (indice_courant == indice)
                        return adresse; //adresse du indicième maillon  indice = 0: 1er maillon, indice = 1 : 2ème maillon ...
                    indice_courant++;
                }
                return null; //jamais atteint
    	    }
     
     
     
            void liste_inserer_debut(Liste l, int valeur)
            {
                Liste nouv = null;
                nouv.val = (char)valeur;
                nouv.suivant = l;
                l = nouv;
            }
     
            void liste_inserer(Liste l, Liste avant, int valeur)
            {
                liste_inserer_debut(avant.suivant, valeur);
            }
     
     
            void liste_supprimer(Liste l, int indice)			// liste_supprimer (liste & l , element e)
            {
                                				// inutile ou assert ( l ! = NULL )
                if (indice == 0)					// if ( l == element )
                { // supprimer un élément
                    Liste a_detruire = l;
                    l = l.suivant;
     
                }
                else
                {
                    liste_supprimer(l.suivant, indice - 1);
                }
            }
     
        }
    }
    Mon problème est au niveau du premier code, quand je fais " public Liste liste;"
    Cela ne peut pas fonctionner? Comment puis je fais pour utiliser mon module de liste dans mon Form.cs pour créer ma liste à partir du tableau ?

    Désolé pour ces questions qui doivent vous paraître plus qu'idiote.

    Merci de votre temps,

    Sylvanocry

  8. #8
    Membre émérite
    Homme Profil pro
    Développeur .NET
    Inscrit en
    Avril 2006
    Messages
    1 627
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Avril 2006
    Messages : 1 627
    Points : 2 331
    Points
    2 331
    Par défaut
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    public Liste liste = null;
    ...
    liste = listeEnParam;//On référence la liste
    liste.Prop = 1;//on manipule les propriétés
    Quand tu écris ça, tu t'exposes à une nullreferenceException
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    void liste_inserer_debut(Liste l, int valeur)
            {
                Liste nouv = null;
                nouv.val = (char)valeur;//nouv est null, donc nouv.val KABOOOM
                nouv.suivant = l;
                l = nouv;
            }

  9. #9
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    A aucun moment tu n'initialises ta variable liste. Il faut explicitement appeler le constructeur, soit directement à la déclaration, soit ailleurs dans le code.

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    public Liste liste = new Liste();
    D'autre part, ta classe Liste contient plein de méthodes qui prennent en paramètre une liste, et ne travaillent que sur cette liste passée en paramètre (et jamais sur la liste courante "this"). En programmation orientée objet, on ne s'y prend pas comme ça. En général les méthodes d'instance d'une classe travaillent sur l'instance courante de la classe. Tu devrais réécrire tes méthodes comme ça :

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
            int liste_longueur() // pas de paramètre, on va travailler sur this
            {
                Liste courant = null;
                int taille = 0;
                courant = this;
     
                while (courant != null)
                {
                    taille++;
                    courant = courant.suivant;
                }
     
                return taille;
            }

  10. #10
    Rédacteur
    Avatar de Nathanael Marchand
    Homme Profil pro
    Expert .Net So@t
    Inscrit en
    Octobre 2008
    Messages
    3 615
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 38
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Expert .Net So@t
    Secteur : Conseil

    Informations forums :
    Inscription : Octobre 2008
    Messages : 3 615
    Points : 8 082
    Points
    8 082
    Par défaut
    De plus je dirais qu'il existe deja nativement des conteneurs dans .Net: des lists, hashsets, stacks, queues, dictionaries, etc.
    Pourquoi s'embeter à réinventer la roue?

  11. #11
    Rédacteur/Modérateur


    Homme Profil pro
    Développeur .NET
    Inscrit en
    Février 2004
    Messages
    19 875
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations professionnelles :
    Activité : Développeur .NET
    Secteur : High Tech - Éditeur de logiciels

    Informations forums :
    Inscription : Février 2004
    Messages : 19 875
    Points : 39 753
    Points
    39 753
    Par défaut
    Citation Envoyé par PitMaverick78 Voir le message
    De plus je dirais qu'il existe deja nativement des conteneurs dans .Net: des lists, hashsets, stacks, queues, dictionaries, etc.
    Pourquoi s'embeter à réinventer la roue?
    Tout à fait d'accord dans le principe, mais pour débuter ça fait pas de mal de réinventer un peu pour bien comprendre le langage

  12. #12
    Membre émérite Avatar de Guulh
    Homme Profil pro
    Inscrit en
    Septembre 2007
    Messages
    2 160
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 42
    Localisation : France, Paris (Île de France)

    Informations forums :
    Inscription : Septembre 2007
    Messages : 2 160
    Points : 2 925
    Points
    2 925
    Par défaut
    Citation Envoyé par tomlev Voir le message
    Tout à fait d'accord dans le principe, mais pour débuter ça fait pas de mal de réinventer un peu pour bien comprendre le langage
    Absolument Découvrir, l'expérience aidant, que le code que l'on a produit lorsque l'on ne connait pas bien C# peut se ré-écrire en moins de 10 lignes (à mon avis ici, deux trois coups de Linq suffisent pour implémenter l'algo d'Huffman) est un mélange bizarre de satisfaction d'avoir progressé et d'impression d'avoir perdu son temps
    Ceci dit, on aborde les problèmes différemment dans un langage bas niveau comme C et dans un langage au framework très complet comme C#. J'ai connu des devs qui n'arrivaient pas à s'y faire, et qui persistaient à utiliser leur implémentation de liste chaînée maison (ou leurs loggers ou leur surcouche aux sockets-mais-si-je-te-dis-que-ton-wcf-et-ton-remoting-c'est-tout-pourri). Il y a des habitudes à perdre

Discussions similaires

  1. Amélioration de l'algorithme de Huffman
    Par Nosper dans le forum Algorithmes et structures de données
    Réponses: 8
    Dernier message: 28/08/2012, 01h10
  2. huffman
    Par Jero13 dans le forum C
    Réponses: 4
    Dernier message: 29/11/2005, 19h54
  3. arbre d'huffman
    Par junior7872 dans le forum Algorithmes et structures de données
    Réponses: 6
    Dernier message: 23/05/2005, 23h00
  4. cherche algos Delphi pour : Huffman, R.S.A, D.E.S.
    Par X-Delphi dans le forum Débuter
    Réponses: 3
    Dernier message: 24/08/2002, 18h51
  5. Algorithme de Huffman
    Par mmuller57 dans le forum Algorithmes et structures de données
    Réponses: 3
    Dernier message: 15/05/2002, 11h47

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo