Rumah > pembangunan bahagian belakang > C++ > Bagaimana Kita Boleh Menjana Semua Pembahagian Set Set Diberikan?

Bagaimana Kita Boleh Menjana Semua Pembahagian Set Set Diberikan?

Barbara Streisand
Lepaskan: 2024-12-27 10:40:10
asal
341 orang telah melayarinya

How Can We Generate All Set Partitions of a Given Set?

Menjana Semua Pembahagian Set

Salah satu masalah asas dalam matematik gabungan ialah mencari semua partition bagi set tertentu. Pembahagian set membahagikan set kepada subset berpisah bukan kosong, dirujuk sebagai blok atau bahagian.

Dalam masalah ini, kami mencari kaedah untuk menghitung semua partition bagi set dengan elemen yang berbeza. Pertimbangkan set {1, 2, 3}. Pembahagiannya ialah:

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

Algoritma Pembahagian

Tugas boleh dipecahkan kepada dua submasalah: pembahagian kepada dua bahagian dan pembahagian bahagian kepada beberapa bahagian.

Dua Bahagian Pembahagian

Untuk set elemen n, semua partition dua bahagian boleh dijana dengan mewakili setiap elemen sebagai sedikit dalam corak n-bit. Bit 0 menunjukkan penempatan di bahagian pertama, dan 1 bit menunjukkan penempatan di bahagian kedua. Untuk mengelakkan hasil pendua apabila menukar bahagian, kami sentiasa menetapkan elemen pertama kepada bahagian pertama. Ini meninggalkan (2^(n-1))-1 corak dua bahagian yang unik.

Pembahagian Rekursif

Dengan teknik pembahagian dua bahagian, kami boleh membina semua partition secara rekursif.

  1. Mulakan dengan bahagian tetap kosong dan set asal sebagai akhiran.
  2. Janakan sekatan dua bahagian akhiran.
  3. Untuk setiap sekatan akhiran, bahagikan secara rekursif bahagian kedua kepada beberapa bahagian.
  4. Gabungkan bahagian tetap dengan rekursif partition untuk mendapatkan semua partition yang mengandungi bahagian tetap.
  5. Ulang langkah 4 sehingga semua elemen adalah dipisahkan.

Pelaksanaan C#

Pelaksanaan C# berikut menggunakan algoritma pembahagian rekursif:

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) {
            // Trivial partition: fixed parts followed by all suffix elements as a single block
            yield return fixedParts.Concat(new[] { suffixElements }).ToArray();

            // Two-group-partitions of suffix elements and their recursive sub-partitions
            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) {
            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());
            }
        }
    }
}
Salin selepas log masuk

Atas ialah kandungan terperinci Bagaimana Kita Boleh Menjana Semua Pembahagian Set Set Diberikan?. Untuk maklumat lanjut, sila ikut artikel berkaitan lain di laman web China PHP!

sumber:php.cn
Kenyataan Laman Web ini
Kandungan artikel ini disumbangkan secara sukarela oleh netizen, dan hak cipta adalah milik pengarang asal. Laman web ini tidak memikul tanggungjawab undang-undang yang sepadan. Jika anda menemui sebarang kandungan yang disyaki plagiarisme atau pelanggaran, sila hubungi admin@php.cn
Artikel terbaru oleh pengarang
Tutorial Popular
Lagi>
Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan