Maison >développement back-end >C++ >Comment pouvons-nous trouver de manière récursive toutes les partitions d'un ensemble ?
Recherche de toutes les partitions d'un ensemble
En mathématiques, une partition d'un ensemble est une collection de sous-ensembles disjoints (blocs ou cellules) dont union est l’ensemble original. Trouver toutes les partitions d'un ensemble est un problème combinatoire classique avec des applications dans de nombreux domaines.
Solution récursive
Une solution récursive peut résoudre efficacement ce problème. L'algorithme commence par générer toutes les partitions possibles en deux parties de l'ensemble donné. Pour chaque partition en deux parties, la deuxième partie est ensuite divisée en deux parties, ce qui donne des partitions en trois parties. Ce processus se poursuit de manière récursive jusqu'à ce que toutes les partitions soient trouvées.
Implémentation
Voici une implémentation C# de l'algorithme récursif :
using System; using System.Collections.Generic; using System.Linq; namespace Partitioning { public static class Partitioning { public static IEnumerable<T[][]> GetAllPartitions<T>(T[] elements) { return GetAllPartitions(new T[][]{}, elements); } private static IEnumerable<T[][]> GetAllPartitions<T>( T[][] fixedParts, T[] suffixElements) { // A trivial partition consists of the fixed parts // followed by all suffix elements as one block yield return fixedParts.Concat(new[] { suffixElements }).ToArray(); // Get all two-group-partitions of the suffix elements // and sub-divide them recursively var suffixPartitions = GetTuplePartitions(suffixElements); foreach (Tuple<T[], T[]> suffixPartition in suffixPartitions) { var subPartitions = GetAllPartitions( fixedParts.Concat(new[] { suffixPartition.Item1 }).ToArray(), suffixPartition.Item2); foreach (var subPartition in subPartitions) { yield return subPartition; } } } private static IEnumerable<Tuple<T[], T[]>> GetTuplePartitions<T>( T[] elements) { // No result if less than 2 elements if (elements.Length < 2) yield break; // Generate all 2-part partitions for (int pattern = 1; pattern < 1 << (elements.Length - 1); pattern++) { // Create the two result sets and // assign the first element to the first set List<T>[] resultSets = { new List<T> { elements[0] }, new List<T>() }; // Distribute the remaining elements for (int index = 1; index < elements.Length; index++) { resultSets[(pattern >> (index - 1)) & 1].Add(elements[index]); } yield return Tuple.Create( resultSets[0].ToArray(), resultSets[1].ToArray()); } } } }
Explication
La méthode GetAllPartitions prend un ensemble d'éléments d'entrée et génère toutes les partitions possibles. Il appelle d'abord GetTuplePartitions pour générer toutes les partitions en deux parties des éléments du sous-ensemble. Pour chaque partition en deux parties, il appelle de manière récursive GetAllPartitions. Ce processus récursif se poursuit jusqu'à ce que toutes les partitions soient trouvées.
La méthode GetTuplePartitions génère toutes les partitions en deux parties possibles d'un ensemble. Pour ce faire, il parcourt tous les modèles de bits possibles (c'est-à-dire les nombres binaires) qui représentent l'affectation d'éléments à deux partitions.
Exemple
Pour l'ensemble {1 , 2, 3}, la méthode GetAllPartitions générerait les partitions suivantes :
{ {1}, {2}, {3} } { {1, 2}, {3} } { {1, 3}, {2} } { {1}, {2, 3} } { {1, 2, 3} }
Cet algorithme génère efficacement toutes partitions d'un ensemble, ce qui en fait un outil précieux dans diverses applications, telles que l'optimisation combinatoire et l'analyse de données.
Ce qui précède est le contenu détaillé de. pour plus d'informations, suivez d'autres articles connexes sur le site Web de PHP en chinois!