首頁 > 後端開發 > C++ > 如何在 C# 中使用遞歸方法高效產生集合的所有分區?

如何在 C# 中使用遞歸方法高效產生集合的所有分區?

Barbara Streisand
發布: 2024-12-30 10:53:14
原創
824 人瀏覽過

How to Efficiently Generate All Partitions of a Set Using a Recursive Approach in C#?

產生集合的分區

將集合分成不同的子集(稱為分區)是一種常見的數學運算。本文深入研究了一種有效的方法來劃分集合,確保不會因順序無關而重複。

遞歸方法

我們的解決方案採用遞歸策略,從最簡單的場景開始:剛好分成兩部分。透過將每個元素表示為一個位元(第一部分為 0,第二部分為 1),我們透過始終將第一個元素放置在第一部分中來避免重複結果。

接下來,我們深入研究遞歸函數解決更複雜的分區。此函數對原始集合進行操作,尋找所有兩部分分區。每個分區的第二部分被遞歸地分成兩部分,產生三個部分分區。這個過程一直持續到整個集合被分區。

實作

以下是分區演算法的C# 實作:

using System;
using System.Collections.Generic;
using System.Linq;

namespace PartitionTest {
    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(new[] { 1, 2, , 4 }) 產生以下內容分區:

{ {1, 2, 3, 4} },
{ {1, 3, 4}, {2} },
{ {1, 2, 4}, {3} },
{ {1, 4}, {2, 3} },
{ {1, 4}, {2}, {3} },
{ {1, 2, 3}, {4} },
{ {1, 3}, {2, 4} },
{ {1, 3}, {2}, {4} },
{ {1, 2}, {3, 4} },
{ {1, 2}, {3}, {4} },
{ {1}, {2, 3, 4} },
{ {1}, {2, 4}, {3} },
{ {1}, {2, 3}, {4} },
{ {1}, {2}, {3, 4} },
{ {1}, {2}, {3}, {4} }.
登入後複製

以上是如何在 C# 中使用遞歸方法高效產生集合的所有分區?的詳細內容。更多資訊請關注PHP中文網其他相關文章!

來源:php.cn
本網站聲明
本文內容由網友自願投稿,版權歸原作者所有。本站不承擔相應的法律責任。如發現涉嫌抄襲或侵權的內容,請聯絡admin@php.cn
作者最新文章
熱門教學
更多>
最新下載
更多>
網站特效
網站源碼
網站素材
前端模板