Outils d'utilisateurs

Outils du Site


rechercher

Différences

Cette page vous donne les différences entre la révision choisie et la version actuelle de la page.

Lien vers cette vue

rechercher [2016/01/08 01:38]
gbdivers
rechercher [2017/01/16 19:27] (Version actuelle)
gbdivers
Ligne 1: Ligne 1:
  
-^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^+[[comparer|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[iterateurs|Chapitre suivant]] ^
  
  
Ligne 11: Ligne 11:
 Pour organiser un peu les algorithmes de la bibliothèque standard, la [[http://en.cppreference.com/w/cpp/algorithm|page de documentation sur cppreference.com]] sépare les algorithmes en plusieurs catégories. Vous allez voir dans ce chapitre quelques algorithmes notables, ce qui va permettre d'introduire quelques notions importantes, vous apprendre à utiliser au mieux les algorithmes et à lire la page de documentation. Pour organiser un peu les algorithmes de la bibliothèque standard, la [[http://en.cppreference.com/w/cpp/algorithm|page de documentation sur cppreference.com]] sépare les algorithmes en plusieurs catégories. Vous allez voir dans ce chapitre quelques algorithmes notables, ce qui va permettre d'introduire quelques notions importantes, vous apprendre à utiliser au mieux les algorithmes et à lire la page de documentation.
  
-Note : des exercices seront ajoutés par la suite à ce coursIls vous permettront d'étudier et pratiquer plus en détail ces algorithmes.+Ce chapitre détaille plus particulièrement les algorithmes qui ne retournent pas d'itérateur et qui ne nécessitent donc pas de détailler ce conceptLes itérateurs seront détaillés dans le chapitre suivant, ainsi que d'autres algorithmes de la bibliothèques standard.
  
 +Note : des exercices seront ajoutés par la suite à ce cours. Ils vous permettront d'étudier et pratiquer plus en détail ces algorithmes.
  
 ===== Les algorithmes non modifiants ===== ===== Les algorithmes non modifiants =====
  
-Les algorithmes non modifiants (//non-modifying sequence operations//). Ce sont des algorithmes qui ne modifient pas les collections sur les quelles ils sont utilisés. Vous allez trouvé dans cette catégorie par exemple l'algorithme d'égalité ''std::equal'' que vous avez déjà vu, ainsi que les algorithmes de recherche (en premier lieu ''std::find''), les algorithmes de comptage (''std::count'') et l'algorithme ''std::for_each'' (qui permet d'appeler une fonction sur chaque élément d'une collection).+Les algorithmes non modifiants (//non-modifying sequence operations//). Ce sont des algorithmes qui ne modifient pas les collections sur les quelles ils sont utilisés. Vous allez trouver dans cette catégorie par exemple l'algorithme d'égalité ''std::equal'' que vous avez déjà vu, ainsi que les algorithmes de recherche (en premier lieu ''std::find''), les algorithmes de comptage (''std::count'') et l'algorithme ''std::for_each'' (qui permet d'appeler une fonction sur chaque élément d'une collection).
  
-Un algorithme non modifiants va donc prendre une collection sans la modifier et retourner un résultat. La valeur retournée peut être utiliser directement ou enregistrée dans une variable, comme n'importe quelle valeur. Le type de la valeur retournée dépend de l’algorithme et du type de collection, le plus simple est d'utiliser l’inférence de type pour créer une variable (consulter la documentation pour connaitre le type exact).+Un algorithme non modifiants va donc prendre une collection sans la modifier et retourner un résultat. La valeur retournée peut être utilisée directement ou enregistrée dans une variable, comme n'importe quelle valeur. Le type de la valeur retournée dépend de l’algorithme et du type de collection, le plus simple est d'utiliser l’inférence de type pour créer une variable (consulter la documentation pour connaitre le type exact).
  
 <note>Les exemples de code suivants utilisent une chaîne, pour simplifier l’écriture du code et l'affichage du résultat. N'oubliez pas qu'une chaîne est une collection de caractères.</note> <note>Les exemples de code suivants utilisent une chaîne, pour simplifier l’écriture du code et l'affichage du résultat. N'oubliez pas qu'une chaîne est une collection de caractères.</note>
Ligne 53: Ligne 54:
  
  
-==== std::all_of, std::any_of et std::none_of ====+==== std::count et std::count_if ====
  
-Les algorithmes [[http://en.cppreference.com/w/cpp/algorithm/count|std::count et std::count_if]] permettent le nombre d’éléments d'une collection correspondant respectivement une valeur et un prédicat. Ces algorithmes retournent une valeur entière signée.+Les algorithmes [[http://en.cppreference.com/w/cpp/algorithm/count|std::count et std::count_if]] retournent le nombre d’éléments d'une collection correspondant respectivement à une valeur et un prédicat. Ces algorithmes retournent une valeur entière signée.
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 80: Ligne 81:
 ==== std::equal ==== ==== std::equal ====
  
-Et bien sur, vous avez déjà vu l'algorithme [[http://en.cppreference.com/w/cpp/algorithm/equal|std::equal]].+Et bien sûr, vous avez déjà vu l'algorithme [[http://en.cppreference.com/w/cpp/algorithm/equal|std::equal]].
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 107: Ligne 108:
  
 Les algorithmes modifiants sont de deux types : les algorithmes qui modifient directement une collection et les algorithmes qui utilisent une collection et modifient une autre collection. Les algorithmes modifiants sont de deux types : les algorithmes qui modifient directement une collection et les algorithmes qui utilisent une collection et modifient une autre collection.
 +
 +Par exemple :
 +
 +<code>
 +std::fill(begin(in), end(in), value);                       // seulement in
 +std::transform(begin(in), end(in), begin(out), operation);  // in et out
 +</code>
 +
 +Mais il est généralement possible d'utiliser le second type d'algo modifiant avec la même collection en entrée et sortie :
 +
 +<code>
 +std::transform(begin(in), end(in), begin(in), operation); 
 +</code>
 +
 +Dans le premier cas, transforme les éléments de ''in'' et met le résultat dans ''out''. Dans le second cas, transforme les éléments de ''in'' et met le résultat dans ''in''. (les valeurs initiales sont donc perdues).
  
  
Ligne 112: Ligne 128:
  
 Note : pas de contrôle de dépassement de collection. Note : pas de contrôle de dépassement de collection.
 +
 +Equivalent : ''std::move'', mais sera vu plus tard.
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 125: Ligne 143:
     std::string s4       { "........................................" };     std::string s4       { "........................................" };
          
-    std::copy(begin(s1), end(s1), begin(s2));+    std::copy(cbegin(s1), cend(s1), begin(s2));
     std::cout << s2 << std::endl;     std::cout << s2 << std::endl;
          
-    std::copy_if(begin(s1), end(s1), begin(s3), isalpha);+    std::copy_if(cbegin(s1), cend(s1), begin(s3), isalpha);
     std::cout << s3 << std::endl;     std::cout << s3 << std::endl;
          
-    std::copy_n(begin(s1), 10, begin(s4));+    std::copy_n(cbegin(s1), 10, begin(s4));
     std::cout << s4 << std::endl;     std::cout << s4 << std::endl;
 } }
Ligne 147: Ligne 165:
  
 Note : pas de contrôle de dépassement de collection. Note : pas de contrôle de dépassement de collection.
 +
 +Equivalent : ''std::move_backward'', mais sera vu plus tard.
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 158: Ligne 178:
     std::string s3       { "........................................" };     std::string s3       { "........................................" };
          
-    std::copy(begin(s1), begin(s1) + 10, begin(s2) + 15);+    std::copy(begin(s1) + 10, begin(s1) + 15, begin(s2) + 10);
     std::cout << s2 << std::endl;     std::cout << s2 << std::endl;
          
-    std::copy_backward(begin(s1), begin(s1) + 10, begin(s2) + 15);+    std::copy_backward(begin(s1) + 10, begin(s1) + 15, begin(s3) + 10);
     std::cout << s3 << std::endl;     std::cout << s3 << std::endl;
 } }
Ligne 169: Ligne 189:
  
 <code> <code>
 +..........a8943......................... 
 +.....a8943..............................
 </code> </code>
  
- +==== std::fill et std::fill_n ====
-==== std::move et std::move_backward ====+
  
 <code cpp main.cpp> <code cpp main.cpp>
Ligne 197: Ligne 217:
  
  
-==== std::fill et std::fill_n ====+==== std::transform ====
  
-<code cpp main.cpp>+Différent des autres algos, ne prend pas un prédicat (objet appelable qui retourne un booléen), mais prend en paramètre un opérateur unaire ou binaire (selon la version de ''transform'' appelée).  
 + 
 +La documentation précise la signature des fonctions (in = input = entrée, out = output = sortie) :  
 + 
 +<code cpp
 +// unaire 
 +TypeOut fun1(const Type &a); 
 +std::transform(std::begin(in), std::end(in), std::begin(out), fun1); 
 + 
 +// binaire 
 +TypeOut fun2(const Type1 &a, const Type2 &b); 
 +std::transform(std::begin(in1), std::end(in1), std::begin(in2), std::begin(out), fun2); 
 +</code> 
 + 
 +Par exemple : 
 + 
 +Version unaire : 
 + 
 +<code cpp>
 #include <iostream> #include <iostream>
 #include <string> #include <string>
Ligne 205: Ligne 243:
    
 int main() { int main() {
-    std::string s { "1234567890" }; +    std::string s { "azerty" }; 
-    std::fill(begin(s), end(s), 'A'); +    std::transform(begin(s), end(s), begin(s), toupper);
-    std::cout << s << std::endl; +
-    std::fill_n(begin(s), 5, '1');+
     std::cout << s << std::endl;     std::cout << s << std::endl;
 } }
Ligne 216: Ligne 252:
  
 <code> <code>
-AAAAAAAAAA +AZERTY
-11111AAAAA+
 </code> </code>
  
 +Version binaire :
  
-==== std::transform ====+<code cpp> 
 +#include <iostream> 
 +#include <functional> 
 +#include <algorithm> 
 +#include <vector> 
 +  
 +int main() { 
 +    std::vector<int> v1 { 1, 2, 3, 4 }; 
 +    const std::vector<int> v2 { -1, 2, -1, 2 }; 
 +    std::transform(begin(v1), end(v1), begin(v2), begin(v1), std::multiplies<int>()); 
 +    for (auto i: v1) std::cout << i << ' '; 
 +    std::cout << std::endl; 
 +
 +</code>
  
-Rôle de cet algorithme prendre une collection et appliquer une fonction ''fun'' sur chaque élément. Cf. la signature de la documentation. Contrairement aux algorithmes que l'on a déjà vu, il ne faut pas fournir un prédicat (i.e. un foncteur qui retourne un booléen), mais une fonction unaire ou binaire (selon la version de ''transform'' appelée). +affiche :
  
-La documentation précise la signature des fonctions : +<code> 
 +-1 4 -3 8 
 +</code>
  
-<code cpp> +==== std::generate et std::generate_n ==== 
-Ret fun(const Type &amp;a);                  // unaire + 
-Ret fun(const Type1 &amp;a, const Type2 &amp;b); // binaire+avec rand ? 
 + 
 + 
 +==== std::remove et std::replace ==== 
 + 
 +<code cpp main.cpp> 
 +#include <iostream> 
 +#include <string> 
 +#include <cctype> 
 +#include <algorithm> 
 +  
 +int main() { 
 +    std::string s1 { &quot;f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::remove(begin(s1), end(s1), '7'); 
 +    std::cout << s1 << std::endl; 
 +     
 +    std::string s2 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }
 +    std::remove_if(begin(s2), end(s2), isdigit); 
 +    std::cout << s2 << std::endl; 
 +     
 +    const std::string s3 { &quot;f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::string s4       { "........................................" }; 
 +    std::remove_copy(begin(s3)end(s3), begin(s4), '7'); 
 +    std::cout << s4 << std::endl; 
 +     
 +    const std::string s5 { &quot;f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::string s6       { "........................................" }; 
 +    std::remove_copy_if(begin(s5), end(s5), begin(s6), isdigit); 
 +    std::cout << s6<< std::endl; 
 +}
 </code> </code>
  
-Ce qui est important à comprendre est que les algorithmes peuvent avoir des signatures spécifiques. Il ne faut pas hésiter à consulter la documentation pour savoir la syntaxe exacte à utiliser.+affiche :
  
-Avec les lambda génériques, l'utilisation de ''transform'' est assez proche de ce que l'on a déjà utiliséVersion unaire :+<code> 
 +f9c02b6c9da8943feaea4966ba41d65de2feee7e 
 +fcbcdafeaeabaddefeea4966ba7417d65de2fe7e 
 +f9c02b6c9da8943feaea4966ba41d65de2fee... 
 +fcbcdafeaeabaddefee..................... 
 +</code>
  
-<code cpp> + 
-std::transform(std::begin(v), std::end(v), std::begin(v), [](auto value){ return value + 1; });+<code cpp main.cpp> 
 +#include <iostream> 
 +#include <string> 
 +#include <cctype> 
 +#include <algorithm> 
 +  
 +int main() { 
 +    std::string s1 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::replace(begin(s1), end(s1), '7', '.'); 
 +    std::cout << s1 << std::endl; 
 +     
 +    std::string s2 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::replace_if(begin(s2), end(s2), isdigit, '.'); 
 +    std::cout << s2 << std::endl; 
 +     
 +    const std::string s3 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" }; 
 +    std::string s4       { "........................................" }; 
 +    std::replace_copy(begin(s3), end(s3), begin(s4), '7', '.'); 
 +    std::cout << s4 << std::endl; 
 +     
 +    const std::string s5 "f9c02b6c9da8943feaea4966ba7417d65de2fe7e"; }
 +    std::string s6       { "........................................" }; 
 +    std::replace_copy_if(begin(s5), end(s5), begin(s6), isdigit, '.'); 
 +    std::cout << s6<< std::endl; 
 +}
 </code> </code>
  
-incrémente de 1 chaque élément.+affiche :
  
-Version binaire :+<code> 
 +f9c02b6c9da8943feaea4966ba.41.d65de2fe.e 
 +f.c..b.c.da....feaea....ba....d..de.fe.e 
 +f9c02b6c9da8943feaea4966ba.41.d65de2fe.e 
 +f.c..b.c.da....feaea....ba....d..de.fe.e 
 +</code>
  
-<code cpp> +==== std::swap etstd::swap_ranges ==== 
-std::transform(std::begin(v1), std::end(v1), std::begin(v2), std::begin(v1),  + 
-    [](auto lhs, auto rhs)return lhs + rhs; });+std::swap ne travaille pas sur des collections en particulier. 
 + 
 +<code cpp main.cpp> 
 +#include <iostream> 
 +#include <string> 
 +#include <algorithm> 
 +  
 +int main() { 
 +    std::string s1 { "azerty" }; 
 +    std::string s2 { "123456" }; 
 +    std::swap(s1s2); 
 +    std::cout << s1 << std::endl; 
 +    std::cout << s2 << std::endl; 
 +     
 +    int x 123 }; 
 +    int y { 456 }
 +    std::swap(x, y); 
 +    std::cout << x << std::endl; 
 +    std::cout << y << std::endl; 
 +}
 </code> </code>
  
-additionne deux à deux, les éléments des deux vecteurs.+affiche :
  
 +<code>
 +123456
 +azerty
 +456
 +123
 +</code>
  
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "azerty" };
 +    std::string s2 { "123456" };
 +    std::swap_ranges(begin(s1), begin(s1) + 3, begin(s2));
 +    std::cout << s1 << std::endl;
 +    std::cout << s2 << std::endl;
 +}
 +</code>
  
 +affiche :
  
 +<code>
 +123rty
 +aze456
 +</code>
 +
 +iter_swap ?
 +
 +==== reverse et reverse_copy ====
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "azerty" };
 +    std::reverse(begin(s1), end(s1));
 +    std::cout << s1 << std::endl;
 +    
 +    const std::string s2 { "azerty" };
 +    std::string s3       { "......" };
 +    std::reverse_copy(begin(s2), end(s2), begin(s3));
 +    std::cout << s3 << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +ytreza
 +ytreza
 +</code>
 +
 +
 +==== rotate ====
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "azerty" };
 +    std::rotate(begin(s1), begin(s1) + 2, end(s1));
 +    std::cout << s1 << std::endl;
 +    
 +    const std::string s2 { "azerty" };
 +    std::string s3       { "......" };
 +    std::rotate_copy(begin(s2), begin(s2) + 2, end(s2), begin(s3));
 +    std::cout << s3 << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +ertyaz
 +ertyaz
 +</code>
 +
 +
 +==== shuffle ====
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 +#include <random>
 + 
 +int main() {
 +    std::string s { "azerty" };
 +    std::random_device rd;
 +    std::mt19937 g(rd());
 +    std::shuffle(begin(s), end(s), g);
 +    std::cout << s << std::endl;
 +}
 +</code>
 +
 +affiche par exemple :
 +
 +<code>
 +yazert
 +</code>
 +
 +
 +==== unique ====
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" };
 +    std::sort(begin(s1), end(s1));
 +    auto last = std::unique(begin(s1), end(s1));
 +    std::cout << std::string(begin(s1), last) << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +0123456789abcdef
 +</code>
  
  
Ligne 259: Ligne 517:
  
 Les algorithmes de partitionnement (//partitioning operations//) permettent séparer une collection en deux sous-collections. Les algorithmes de partitionnement (//partitioning operations//) permettent séparer une collection en deux sous-collections.
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" };
 +    std::partition(begin(s1), end(s1), isdigit);
 +    std::cout << s1 << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +792025669718943476694aeabaefaddcbdecfefe
 +</code>
  
  
Ligne 265: Ligne 541:
 Les algorithmes de tri (//sorting operations//) permettent de trier les éléments d'une collection. Les algorithmes de tri (//sorting operations//) permettent de trier les éléments d'une collection.
  
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s1 { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" };
 +    std::sort(begin(s1), end(s1));
 +    std::cout << s1 << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +012234445666677789999aaaabbccdddeeeeefff
 +</code>
  
  
Ligne 270: Ligne 563:
  
 Les algorithmes binaires de recherche (//binary search operations//) permettent de rechercher un élément dans une collection triée. Les algorithmes binaires de recherche (//binary search operations//) permettent de rechercher un élément dans une collection triée.
 +
 +<code cpp main.cpp>
 +#include <iostream>
 +#include <string>
 +#include <algorithm>
 + 
 +int main() {
 +    std::string s { "f9c02b6c9da8943feaea4966ba7417d65de2fe7e" };
 +    std::sort(begin(s), end(s));
 +    std::cout << s << std::endl;
 +    
 +    const auto result = binary_search(begin(s), end(s), 'a');
 +    std::cout << std::boolalpha << result << std::endl;
 +}
 +</code>
 +
 +affiche :
 +
 +<code>
 +012234445666677789999aaaabbccdddeeeeefff
 +true
 +</code>
  
  
Ligne 275: Ligne 590:
  
 Les algorithmes sur les ensembles (//set operations//) permettent de manipuler une collection comme un ensemble d’éléments (donc sans élément en double). Les algorithmes sur les ensembles (//set operations//) permettent de manipuler une collection comme un ensemble d’éléments (donc sans élément en double).
 +
 +
  
  
Ligne 285: Ligne 602:
  
 Les **algorithmes minimum/maximum** permettent de recherche des éléments minimum ou maximum et réaliser des permutations. Les **algorithmes minimum/maximum** permettent de recherche des éléments minimum ou maximum et réaliser des permutations.
 +
 +
  
  
Ligne 291: Ligne 610:
 Les **algorithmes numériques** (//numeric operations//) permettent de travailler sur des collections de nombres. Les **algorithmes numériques** (//numeric operations//) permettent de travailler sur des collections de nombres.
  
-^ Chapitre précédent ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ Chapitre suivant ^+ 
 +<code cpp main.cpp> 
 +#include <iostream> 
 +#include <algorithm> 
 +#include <vector> 
 +#include <numeric> 
 + 
 +int main() { 
 +    std::vector<int> v1(5); 
 +    std::iota(begin(v1), end(v1), 0); 
 +    for(const auto i: v1) { std::cout << i << ' '; } std::cout << std::endl; 
 +     
 +    std::cout << std::accumulate(begin(v1), end(v1), 0) << std::endl; 
 +     
 +    const std::vector<int> v2 = { 2, 3, 4, 0, 1 }; 
 +    std::cout << std::inner_product(begin(v1), end(v1), begin(v2), 0) << std::endl; 
 +    // = 0 * 2 + 1 * 3 + 2 * 4 + 3 * 0 + 4 * 1 
 +     
 +    std::vector<int> v3(v2.size()); 
 +    std::adjacent_difference(begin(v1), end(v1), begin(v3)); 
 +    for(const auto i: v3) { std::cout << i << ' '; } std::cout << std::endl;    
 +     
 +    std::vector<int> v4 { v2 }; 
 +    std::adjacent_difference(begin(v4), end(v4), begin(v4)); 
 +    for(const auto i: v4) { std::cout << i << ' '; } std::cout << std::endl;    
 +
 +</code> 
 + 
 +affiche : 
 + 
 +<code> 
 +0 1 2 3 4  
 +10 
 +15 
 +0 1 1 1 1  
 +2 1 1 -4 1  
 +</code> 
 + 
 + 
 +[[comparer|Chapitre précédent]] ^ [[programmez_avec_le_langage_c|Sommaire principal]] ^ [[iterateurs|Chapitre suivant]] ^ 
rechercher.1452213490.txt.gz · Dernière modification: 2016/01/08 01:38 par gbdivers