2010-09-01 6 views
0

Q:Comment obtenir des valeurs distinctes d'un tableau de différentes tailles?

arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9} 

Ans:

values[]={1,2,5,6,7,9} 

Q:

arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9} 

: Ans

values[]={1,2,5,6,7,9,101,1502} 

ici est ce que je l'ai essayé, mais ne fonctionne pas

for(int i=0;i<(index-1);i++) { 
     if(data[i].age != data[i+1].age) { 
      c=new list; 
      c->value=data[i].age; 
      c->next=NULL; clas++; 
      if(age_head==NULL) { 
       p=c; age_head=c; 
      } 
      for(c=age_head;c!=NULL,c->next!=NULL;p=c,c=c->next) { 
       if(data[i].age!=c->value) 
        found=false; 
       else 
        found=true; 
      } 
      if((age_head!=NULL)&& (found=false)) { 
       p->next=c; c->next=NULL; 
      } 
     } 
    } 
+0

Que proposez-vous? Avez-vous essayé quelque chose? –

+1

Est-ce que ce sont les devoirs? – teukkam

+0

S'il s'agit de devoirs, veuillez l'étiqueter en conséquence. Notez que nous ne faisons pas vos devoirs pour vous - faire un effort, montrer à quel point vous avez et où vous êtes coincé, alors nous sommes heureux de vous aider :-) –

Répondre

4

La première chose que je place dans votre code est

if((age_head!=NULL)&& (found=false)) { 

vous utilisez l'affectation (=) au lieu de l'égalité (==). L'expression doit être

if((age_head!=NULL)&& (found==false)) { 

Puis, dans cette boucle

 for(c=age_head;c!=NULL,c->next!=NULL;p=c,c=c->next) { 

vous êtes à la recherche d'une valeur dans la liste. Toutefois, dans sa forme actuelle, lorsque la boucle se termine, found indique si l'élément dernier dans la liste est égal à c->value. Vous devez vérifier found dans la condition de la boucle (et vous avez besoin et les expressions au lieu de les énumérer séparés par des virgules!):

 for(c=age_head, found = false; !found && c!=NULL && c->next!=NULL; ...) { 

Le résultat de l'opérateur virgule est le résultat de la dernière sous-expression à l'intérieur - Ce n'est certainement pas ce que vous voulez. De plus, avec une virgule, toutes les sous-expressions sont évaluées, ce qui entraîne le déréférencement d'un pointeur nul si c == NULL - alors que l'opérateur && est évalué paresseusement, donc c->next!=NULL est évalué seulement si c != NULL.

La prochaine chose est que vous devez rechercher la valeur dans la liste avant vous l'ajoutez à la liste! Notez également que vous essayez de vérifier deux choses différentes: que l'élément réel data est différent du suivant, et que sa valeur n'est pas encore ajoutée à la liste. La deuxième condition est plus forte - elle fonctionnera toujours, tandis que la première ne fonctionne que si les données d'entrée sont ordonnées. Donc, vous pouvez omettre la première vérification tout à fait. Le résultat de tout ce qui précède, ainsi que quelques autres simplifications et clarifications, est

for(int i=0;i<index;i++) { 
    for(list* c=age_head, found=false; !found&&c&&c->next; p=c,c=c->next) { 
     if(data[i].age==c->value) 
      found=true; 
    } 
    if(!found) { 
     list* newc=new list; 
     newc->value=data[i].age; 
     newc->next=NULL; 
     clas++; 
     if(age_head==NULL) { 
      p=newc; age_head=newc; 
     } else { 
      p->next=newc; newc->next=NULL; 
     } 
    } 
} 

Je ne comprends toujours pas garantir que votre logique de gestion liste chaînée est juste bien :-) Dans sa forme actuelle, votre code est difficile à comprendre, car les différentes étapes logiques ne sont pas séparées. Avec un peu de refactoring, le code pourrait être beaucoup plus clair, par ex.

for(int i=0;i<index;i++) { 
    if(!foundInList(data[i].age)) { 
     addToList(data[i].age); 
    } 
} 

Bien sûr, le serait d'utiliser des conteneurs/algorithmes STL au lieu, comme indiqué dans d'autres réponses plus simple et la plus efficace.Mais je pense qu'il ya beaucoup plus de valeur éducative dans l'amélioration de votre première tentative :-)

+0

if ((age_head! = NULL) && (found == false)) { fait mais toujours pas mal sumthngs mal –

+0

@user, voir ma mise à jour. –

+0

+1, pour votre analyse du code de la question – paercebal

0

vous devez d'abord trier le tableau et que faire quelque chose comme ceci:

for(int i = 0; i < size -1; i++) 
{ 
    if(array[i]!=array[i+1]) 
     unique++; 

     // store it wherever you want to. 
     stored.push(array[i]); 
} 
+0

je ne veux pas de valeurs de coun je veux stocker dem –

2

Si la sortie n'a pas besoin d'être triés , vous pouvez utiliser une table de hachage.

E.g. quelque chose comme ceci:

#include <boost/foreach.hpp> 
#define foreach BOOST_FOREACH 
#include <boost/unordered_set.hpp> 
#include <vector> 
using namespace std; 
using namespace boost; 

int main() { 
    int arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9}; 
    size_t n = sizeof(arr1)/sizeof(int); 
    unordered_set<int> h; 
    for (size_t i = 0; i < n; ++i) 
    h.insert(arr1[i]); 
    vector<int> values; 
    foreach(int a, h) 
    values.push_back(a); 
    return 0; 
} 

L'exécution est alors dans O (n).

Une alternative à ce qui est le tri de la matrice, puis à éliminer les éléments identiques voisins (seul avantage STL est nécessaire). Mais l'environnement d'exécution est en O (n log n):

#include <vector> 
#include <algorithm> 
using namespace std; 

int main() { 
    int arr1[]={1,1,1,2,5,5,6,6,6,6,8,7,9}; 
    size_t n = sizeof(arr1)/sizeof(int); 

    sort(arr1, arr1+n); 
    int *end = unique(arr1, arr1+n); 

    vector<int> values(arr1, end); 

    return 0; 
} 
5

Ce n'est pas le plus efficace, mais il a des valeurs:

  1. Il utilise des objets STL
  2. Il utilise un endroit frais peu connu tour du modèle pour savoir au moment de la compilation de la taille de vos tableaux C comme

...

int a[] = {1,1,1,2,5,5,6,6,6,6,8,7,9} ; 
int b[] = {1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9} ; 

// function setting the set values 
template<size_t size> 
void findDistinctValues(std::set<int> & p_values, int (&p_array)[size]) 
{ 
    // Code modified after Jacob's excellent comment 
    p_values.clear() ; 
    p_values.insert(p_array, p_array + size) ; 

} 

void foo() 
{ 
    std::set<int> values ; 

    findDistinctValues(values, a) ; 
    // values now contain {1, 2, 5, 6, 7, 8, 9} 

    findDistinctValues(values, b) ; 
    // values now contain {1, 2, 5, 6, 7, 8, 9, 101, 1502} 
} 

Une autre version pourrait retourner l'ensemble, au lieu de prendre par référence. Il serait alors:

int a[] = {1,1,1,2,5,5,6,6,6,6,8,7,9} ; 
int b[] = {1,1,1,2,5,5,6,6,6,6,8,7,9,101,1502,1502,1,9} ; 

// function returning the set 
template<size_t size> 
std::set<int> findDistinctValues(int (&p_array)[size]) 
{ 
    // Code modified after Jacob's excellent comment 
    return std::set<int>(p_array, p_array + size) ; 
} 

void foo() 
{ 
    std::set<int> valuesOne = findDistinctValues(a) ; 
    // valuesOne now contain {1, 2, 5, 6, 7, 8, 9} 

    std::set<int> valuesTwo = findDistinctValues(b) ; 
    // valuesTwo now contain {1, 2, 5, 6, 7, 8, 9, 101, 1502} 
} 
+0

Bon truc pour la taille du tableau! –

+0

Puisque vous effacez p_values ​​de toute façon, pourquoi ne pas simplement construire un nouvel ensemble à partir de p_array et l'assigner à p_values ​​à la place? Comme ceci: p_values ​​= std :: set (p_array, p_array + size); Je ne sais pas si cela apparaît correctement, je ne sais pas comment faire du code dans les commentaires. – Jacob

+0

@Cedric H: Je l'ai appris de l'exemple de Microsoft pour strcpy_s, ce qui est assez bien (regardez la surcharge C++): http://msdn.microsoft.com/en-us/library/td1esda9.aspx – paercebal

0
#include <vector> 
#include <algorithm> 
#include <iostream> 

int 
main() 
{ 
    int array[] = { 1, 1, 2, 2, 1, 3, 3, 4, 5, 4, 4, 1, 1, 2 }; 
    std::vector <int>values; 
    values.push_back (array[0]); 
    for (int i = 1; i < sizeof (array)/sizeof (int); ++i) 
    { 
     std::vector <int>::iterator it = 
     std::find (values.begin(), values.end(), array[i]); 
     if (it == values.end()) 
     values.push_back (array[i]); 
    } 

    std::cout << "Result:" << std::endl; 
    for (int i = 0; i < values.size(); i++) 
    std::cout << values[i] << std::endl; 
} 
+0

Notez que l'exécution de ceci est en O (n^2), c'est-à-dire.l'exécution du programme croît de manière quadratique avec la taille du tableau. Utiliser (au moins) tri + unique est dans O (n log n) et est moins de code. – maxschlepzig

2

facilement fait en utilisant STL.

int array[] = { 1, 1, 2, 2, 1, 3, 3, 4, 5, 4, 4, 1, 1, 2 }; 
int nElements = sizeof(array)/sizeof(array[0]); 
std::sort(&array[0], &array[nElements]); 
int newSize = std::unique(&array[0], &array[nElements]) - &array[0]; 
+0

ou au lieu de '& array [0], & array [nElements]' vous pouvez dire 'array, array + nElements'. –

+0

std :: unique ne renvoie pas la nouvelle taille du tableau, il renvoie l'adresse de fin ... – maxschlepzig

+0

doh, vous avez raison. – user434507

0

basé sur des idées/codes ci-dessus, je suis en mesure d'accomplir mon travail sur la recherche de valeurs distinctes dans le tableau C++. Merci à tous ceux qui ont répondu sur ce sujet.

#include <set> 
#include <iostream> 
using namespace std; 
// function setting the set values 
template<size_t size> 
void findDistinctValues(std::set<int> & p_values,int (&p_array)[size]) 
{ 
    // Code modified after Jacob's excellent comment 
    p_values.clear() ; 
    p_values.insert(p_array, p_array + size) ; 

} 

void findDistinctValues2(int arr[],int size) 
{ 
    std::set<int> values_1 ; 
    std::set<int>::iterator it_1; 
    values_1.clear(); 
    values_1.insert(arr,arr+size); 
    for (it_1=values_1.begin(); it_1!=values_1.end(); ++it_1) 
    std::cout << ' ' << *it_1<<endl; 

} 

int main() 
{ 
    int arr[] = {1,6100,4,94,93,-6,2,4,4,5,5,2500,5,4,5,2,3,6,1,15,16,0,0,99,0,0,34,99,6100,2500}; 
    std::set<int> values ; 
    std::set<int>::iterator it; 

    int arr_size = sizeof(arr)/sizeof(int); 
    printf("Total no of array variables: %d\n",arr_size); 
    printf("Output from findDistinctValues (function 1)\n "); 
    findDistinctValues(values, arr) ; 
    for (it=values.begin(); it!=values.end(); ++it) 
    std::cout << ' ' << *it<<endl; 
    std::cout<<endl;  
    std::cout<<values.size()<<endl; //find the size of distict values 

    printf("Output from findDistinctValues (function 2) \n "); 
    findDistinctValues2(arr,arr_size); 

    getchar(); 
    return 0; 
} 
Questions connexes