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 :

Prendre un sous-ensemble d'une matrice


Sujet :

C

Vue hybride

Message précédent Message précédent   Message suivant Message suivant
  1. #1
    Membre éclairé
    Homme Profil pro
    Chercheur en écologie
    Inscrit en
    Février 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en écologie

    Informations forums :
    Inscription : Février 2011
    Messages : 43
    Par défaut Prendre un sous-ensemble d'une matrice
    Bonjour à tous,

    Je débute en C (mais pas en programmation), et j'ai un problème que je n'arrive pas a résoudre…

    Je programme un modèle d'évolution dans les réseaux trophiques, ce qui implique de manipuler des matrices et des vecteurs dans tous les sens. Ca se fait très bien en R, mais c'est long – j'ai donc décidé de le refaire en C.

    Une des choses que je dois faire, c'est prendre un sous-ensemble d'une matrice quand une des espèces s'éteint (quand l'espèce i s'éteint, je dois enlever la ligne i et la colonne i d'une matrice – en R, ça prend une ligne…). J'ai essayé plusieurs solutions, mais sans grand succès. Est-ce qu'il existe une méthode générale pour le faire?

    Merci d'avance

  2. #2
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    Ca dépend comment sont représentées tes matrices en mémoires. Ce sont de bêtes tableaux à deux dimensions ou quelque chose de plus sophistiqué ?

    Si tu n'as pas encore prix le problème sous cet angle, tu peux peut-être chercher une représentation qui permet d'effectuer rapidement les opérations dont tu as le plus besoin.

  3. #3
    Membre éclairé
    Homme Profil pro
    Chercheur en écologie
    Inscrit en
    Février 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en écologie

    Informations forums :
    Inscription : Février 2011
    Messages : 43
    Par défaut
    Citation Envoyé par matafan Voir le message
    Ca dépend comment sont représentées tes matrices en mémoires. Ce sont de bêtes tableaux à deux dimensions ou quelque chose de plus sophistiqué ?

    Si tu n'as pas encore prix le problème sous cet angle, tu peux peut-être chercher une représentation qui permet d'effectuer rapidement les opérations dont tu as le plus besoin.
    Ce sont effectivement de bêtes tableaux a deux dimensions, et ça m'a semblé le plus naturel pour ce type de données (mais la encore, ça vient du fait que je viens de R/Matlab, et que ces deux langages utilisent des matrices).

    Si je garde ces tableaux à deux dimensions, comment je devrai faire?

  4. #4
    Membre expérimenté Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Par défaut
    Comment sont codées tes matrices ?
    Tu utilises un tableau de pointeur ou un tableau à une dimension?

  5. #5
    Membre éclairé
    Homme Profil pro
    Chercheur en écologie
    Inscrit en
    Février 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en écologie

    Informations forums :
    Inscription : Février 2011
    Messages : 43
    Par défaut
    Citation Envoyé par quetzacoatl Voir le message
    Comment sont codées tes matrices ?
    Tu utilises un tableau de pointeur ou un tableau à une dimension?
    Ce sont des matrices carrées, donc ça ressemble à

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
     
    int div = 100;
    double A[div][div];
    Je dirais donc que c'est des tableaux à deux dimensions, et sans pointeurs. Etant vraiment débutant, je ne sais pas trop dans quelle mesure c'est important…

  6. #6
    Membre expérimenté Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Par défaut
    Il est en général déconseillé de déclarer un tableau avec une taille qui est une variable, voici par exemple l'avertissement que met gcc après la compilation de ton code:
    Untitled1.c:4: warning: ISO C90 forbids variable-size array `A'

  7. #7
    Membre éclairé
    Homme Profil pro
    Chercheur en écologie
    Inscrit en
    Février 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en écologie

    Informations forums :
    Inscription : Février 2011
    Messages : 43
    Par défaut
    Citation Envoyé par quetzacoatl Voir le message
    Il est en général déconseillé de déclarer un tableau avec une taille qui est une variable, voici par exemple l'avertissement que met gcc après la compilation de ton code:
    Untitled1.c:4: warning: ISO C90 forbids variable-size array `A'
    Ok, merci pour l'info. Par contre, par définition, la taille de ma matrice va changer au cours du temps (nb d'espèces ^2), et à part en lui donnant une taille qui est une variable, je ne sais pas trop comment faire…

  8. #8
    Membre expérimenté Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Par défaut
    Ce que tu dois faire c'est une allocation dynamique pour pouvoir créer une matrice dont tu ne connais pas la taille avant la compilation(voir malloc() )

  9. #9
    Membre éclairé
    Homme Profil pro
    Chercheur en écologie
    Inscrit en
    Février 2011
    Messages
    43
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : Canada

    Informations professionnelles :
    Activité : Chercheur en écologie

    Informations forums :
    Inscription : Février 2011
    Messages : 43
    Par défaut
    Citation Envoyé par quetzacoatl Voir le message
    Ce que tu dois faire c'est une allocation dynamique pour pouvoir créer une matrice dont tu ne connais pas la taille avant la compilation(voir malloc() )
    OK, je vas donc faire comme ça. Par contre, ça ne résoud pas le problème de départ… Est-ce qu'il y a un moins simple de virer les lignes / colonnes d'une matrice construite de cette manière?

  10. #10
    Membre Expert
    Homme Profil pro
    Ingénieur développement logiciels
    Inscrit en
    Octobre 2008
    Messages
    1 515
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Âge : 47
    Localisation : France

    Informations professionnelles :
    Activité : Ingénieur développement logiciels

    Informations forums :
    Inscription : Octobre 2008
    Messages : 1 515
    Par défaut
    La encore ça va dépendre de ce que tu fais avec tes données. Quand tu dis supprimer la ligne et le colonne i, est-ce que ça veut dire que la dimension de ton tableau (div) diminue de 1 ? Est-ce que tu dois absolument conserver l'ordre des lignes et des colonnes, ou pas nécessairement ?

    Est-ce qu'un algo de ce genre peut convenir :

    - décrémenter div
    - copier la ligne div par dessus la ligne i
    - copier la colonne div par dessus la colonne i

    Ce qui en clair veut dire mettre la dernière ligne à la place de la ligne à supprimer, et la dernière colonne à la place de la colonne à supprimer.

  11. #11
    Expert confirmé
    Avatar de diogene
    Homme Profil pro
    Enseignant Chercheur
    Inscrit en
    Juin 2005
    Messages
    5 761
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Essonne (Île de France)

    Informations professionnelles :
    Activité : Enseignant Chercheur
    Secteur : Enseignement

    Informations forums :
    Inscription : Juin 2005
    Messages : 5 761
    Par défaut
    @ quetzacoatl :
    Simple pas à ma connaissance, mais ça doit être parfaitement faisable en utilisant memcpy() ou des boucles
    On ne peut pas utiliser memcpy() et il faut utiliser memmov()

    Si on a une matrice carrée N*N, il faut supprimer 2*N-1 éléments de la matrice. On peut supprimer une ligne d'un coup et il reste N-1 éléments à supprimer. Cela fait N appels à memmov(), chaque appel devant déplacer une partie du tableau.
    Je crois préférable de faire une boucle et déplacer directement les données.


    Pour la suite, on traite le tableau 2D comme un tableau 1D donc l'élément [i][j] est en position k = i*N+j , k = 0..N*N

    Si on veut supprimer la ligne et la colonne d'indice s (0..N-1), les éléments à éliminer sont en position k avec
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    - pour la ligne s : k = s*N + i   , i= 0..N-1    
      soit k/N == s
    - pour la colonne s : k = i*N + s , i= 0..N-1  
      soit k%N == s
    Il faut déplacer les autres éléments de position k de d positions vers le début du tableau.
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    - si k < s , l'élément n'est pas à déplacer
    
    - si s < k < s*N, 
       le nombre de déplacements est égal au nombre d'éléments de la colonne
       s qui précède k  soit tel que  i*N+s < k   ou   i < (k-s)/N. 
       Alors, d = (k-s)/N +1
    
    - si (s+1)N <= k < N*N,
       le nombre de déplacements dû à la suppression de la colonne est (k-s)/N +1 
       celui dû à la suppression de la ligne est N-1 (un élément est commun à la colonne) 
       Alors d = N+(k-s)/N
    Ceci correspond au code :
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    void suppression(int * t, int s, int dim)
    {
      int k;
      for(k=0; k<dim*dim;k++)
      {
        if(k>s && k<s*dim && k%dim !=s) t[k-(k-s)/dim-1] = t[k];
        if(k>s*dim+dim-1 && k%dim !=s)  t[k-dim-(k-s)/dim] = t[k];
      }
    }
     
     int tab[N][N];
     ....
     suppression(tab[0],i,N);
    ** Attention au choix fait par le posteur d'utiliser les VLA du C99 : si le tableau devient trop grand, ce ne sera plus possible à cause de la taille limitée de la pile.

  12. #12
    Expert confirmé

    Profil pro
    Inscrit en
    Janvier 2007
    Messages
    10 610
    Détails du profil
    Informations personnelles :
    Âge : 67
    Localisation : France

    Informations forums :
    Inscription : Janvier 2007
    Messages : 10 610
    Billets dans le blog
    2
    Par défaut
    Citation Envoyé par diogene Voir le message
    Si on a une matrice carrée N*N, il faut supprimer 2*N-1 éléments de la matrice. On peut supprimer une ligne d'un coup et il reste N-1 éléments à supprimer. Cela fait N appels à memmov(), chaque appel devant déplacer une partie du tableau.
    Je crois préférable de faire une boucle et déplacer directement les données.
    Je suis d'accord, mais je le ferais un tout petit peu autrement (et un peu plus clairement ) :

    Code C : 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
    dec = 0
     
    for ( j = 0 ; j < N ; j++ )
    {
        if ( j == i )
           {
              dec = dec + N ;
           }
         else
          {
              for ( k = 0 : k < N ; k++ )
                {
                    if (  k == i )
                      {
                          dec = dec + 1 ;
                      }
                    else
                        tab[j*N + k - dec] = tab[j*N+k] ;
                 }
         }
      }

  13. #13
    Membre expérimenté Avatar de quetzacoatl
    Profil pro
    Inscrit en
    Janvier 2011
    Messages
    168
    Détails du profil
    Informations personnelles :
    Localisation : France

    Informations forums :
    Inscription : Janvier 2011
    Messages : 168
    Par défaut
    Simple pas à ma connaissance, mais ça doit être parfaitement faisable en utilisant memcpy() ou des boucles

Discussions similaires

  1. [DLL] Extraire un sous-ensemble d'une application
    Par DSGSLA dans le forum Windows
    Réponses: 9
    Dernier message: 23/03/2010, 09h28
  2. Réponses: 4
    Dernier message: 13/01/2009, 18h19
  3. [LINQ To Object] Sous-ensemble d'une liste
    Par farfadet dans le forum Linq
    Réponses: 6
    Dernier message: 17/11/2008, 23h31
  4. RS 2005 - sous-totaux dans une matrice
    Par sandmil dans le forum MS SQL Server
    Réponses: 6
    Dernier message: 11/12/2007, 09h20
  5. sous ensemble d'une liste
    Par adel25 dans le forum C++
    Réponses: 1
    Dernier message: 23/08/2005, 15h50

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