Maison >développement back-end >C++ >Comment pouvons-nous générer de manière récursive toutes les partitions d'un ensemble ?
Partitionnement d'un ensemble : une approche récursive
La tâche de trouver toutes les partitions d'un ensemble se pose fréquemment en informatique et en mathématiques. Une partition divise un ensemble en sous-ensembles disjoints, contenant collectivement tous les éléments de l'ensemble d'origine.
Pour commencer, considérons un problème plus simple : diviser un ensemble en deux sous-ensembles. Pour un ensemble de n éléments, nous pouvons représenter une partition en utilisant un masque de bits binaire. Chaque bit correspond à un élément de l'ensemble, où un 0 indique le placement dans le premier sous-ensemble et un 1 indique le second. Cela garantit que chaque élément est affecté à exactement un sous-ensemble.
Pour gérer la présence du premier élément dans le premier sous-ensemble, nous ne considérons que les masques de bits dont le premier bit est 0. Cela réduit le nombre de masques de bits à 2. ^(n-1).
Pour généraliser cette approche, nous pouvons partitionner un ensemble en plusieurs sous-ensembles de manière récursive. Nous commençons par toutes les partitions en deux parties, puis divisons le deuxième sous-ensemble en deux parties, puis le troisième sous-ensemble, et ainsi de suite. Ce processus récursif produit toutes les partitions possibles.
Voici un exemple d'implémentation en C# qui génère toutes les partitions pour un tableau donné :
using System; using System.Collections.Generic; namespace Partitioning { public static class Program { public static IEnumerable<T[][]> GetAllPartitions<T>(T[] elements) { return GetAllPartitions(new T[][] { }, elements); } private static IEnumerable<T[][]> GetAllPartitions<T>(T[][] fixedParts, T[] suffixElements) { // Trivial partition: fixed parts followed by remaining elements as one block yield return fixedParts.Concat(new[] { suffixElements }).ToArray(); // Get all two-part partitions of suffix elements and subdivide recursively var suffixPartitions = GetTuplePartitions(suffixElements); foreach (Tuple<T[], T[]> suffixPartition in suffixPartitions) { var recursivePartitions = GetAllPartitions(fixedParts.Concat(new[] { suffixPartition.Item1 }).ToArray(), suffixPartition.Item2); foreach (T[][] partition in recursivePartitions) { yield return partition; } } } private static IEnumerable<Tuple<T[], T[]>> GetTuplePartitions<T>(T[] elements) { if (elements.Length < 2) yield break; for (int pattern = 1; pattern < 1 << (elements.Length - 1); pattern++) { List<T>[] resultSets = { new List<T> { elements[0] }, new List<T>() }; 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()); } } } }
L'appel de GetAllPartitions avec un tableau d'éléments génère toutes les partitions possibles. pour cet ensemble.
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!