>백엔드 개발 >C++ >세트의 모든 파티션을 어떻게 재귀적으로 찾을 수 있나요?

세트의 모든 파티션을 어떻게 재귀적으로 찾을 수 있나요?

Linda Hamilton
Linda Hamilton원래의
2024-12-30 16:17:09310검색

How Can We Recursively Find All Partitions of a Set?

집합의 모든 파티션 찾기

수학에서 집합의 파티션은 연결되지 않은 하위 집합(블록 또는 셀)의 모음입니다. Union은 원래 세트입니다. 세트의 모든 파티션을 찾는 것은 다양한 영역의 응용 프로그램에서 발생하는 전형적인 조합 문제입니다.

재귀 솔루션

재귀 솔루션은 이 문제를 효과적으로 해결할 수 있습니다. 알고리즘은 주어진 세트의 가능한 모든 두 부분으로 구성된 파티션을 생성하는 것으로 시작됩니다. 두 부분으로 구성된 각 파티션의 경우 두 번째 부분이 다시 두 부분으로 분할되어 세 부분으로 구성된 파티션이 생성됩니다. 이 프로세스는 모든 파티션을 찾을 때까지 재귀적으로 계속됩니다.

구현

다음은 재귀 알고리즘의 C# 구현입니다.

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());
            }
        }
    }
}

설명

GetAllPartitions 메서드는 입력 세트 요소를 가져와 가능한 모든 파티션을 생성합니다. 먼저 GetTuplePartitions를 호출하여 하위 집합 요소의 두 부분으로 구성된 파티션을 모두 생성합니다. 두 부분으로 구성된 각 파티션에 대해 GetAllPartitions를 재귀적으로 호출합니다. 이 재귀 프로세스는 모든 파티션을 찾을 때까지 계속됩니다.

GetTuplePartitions 메서드는 세트의 가능한 모든 두 부분 파티션을 생성합니다. 두 파티션에 대한 요소 할당을 나타내는 가능한 모든 비트 패턴(예: 이진수)을 반복하여 이를 수행합니다.

세트 {1 , 2, 3}, GetAllPartitions 메서드는 다음 파티션을 생성합니다.

{ {1}, {2}, {3} }
{ {1, 2}, {3} }
{ {1, 3}, {2} }
{ {1}, {2, 3} }
{ {1, 2, 3} }

이것은 알고리즘은 세트의 모든 파티션을 효율적으로 생성하므로 조합 최적화 및 데이터 분석과 같은 다양한 애플리케이션에서 귀중한 도구가 됩니다.

위 내용은 세트의 모든 파티션을 어떻게 재귀적으로 찾을 수 있나요?의 상세 내용입니다. 자세한 내용은 PHP 중국어 웹사이트의 기타 관련 기사를 참조하세요!

성명:
본 글의 내용은 네티즌들의 자발적인 기여로 작성되었으며, 저작권은 원저작자에게 있습니다. 본 사이트는 이에 상응하는 법적 책임을 지지 않습니다. 표절이나 침해가 의심되는 콘텐츠를 발견한 경우 admin@php.cn으로 문의하세요.