求集合冪集的幾種方法


方法1:位運算

冪集即原集合所有子集組成的元素;對原集合中的每個元素取或不取,構成的所有情況,即與原集合所有子集一一對應;對取或不取用二進制1或0表示,即可用2原集合元素個數個數字來表示原集合的所有子集。代碼實現如下:

#include <iostream>
#include <cstdint>//有uint64_t類型的定義
using namespace std;
void funPowerSet(int * b, int iSetLen)//此方法只適用於集合元素小於等於64
{
	for (uint64_t i = 0; i <(1 << iSetLen); i++)
	{
		cout << "{";
		for (uint64_t j = 0; j < iSetLen; j++)
		{
			if (i&(1 << j))
				cout << b[j] << ", ";
		}
		cout << "}\n";
	}
}

(ps: uint64_t,代表64位無符號整數類型。這樣寫需要包含 stdint.h頭文件。這種寫法即能見名知意,又能保證移植時,不會因為類型的范圍出錯。)
以上實現方法的問題是待求集合的元素個數不能超過63,因為c++目前只支持64位整數。
解決辦法是用bitset,不過bitset沒有自增運算,需要自己再給bitset寫個自增函數,整體代碼如下:


#include <iostream>
#include <cstdint>//有uint64_t類型的定義
#include <bitset>
using namespace std;

//不考慮溢出 相當於 ++bs
//如果溢出,bs不改變
template<size_t _Nb>
bitset<_Nb> & add1(bitset<_Nb> &bs){
    int i=0, n=bs.size();
    for(; i<n; i++){
        if(bs[i]==0){
            bs[i]=1;
            break;
        }
        else if(bs[i]==1){
            bs[i]=0;
        }
    }
    return bs;
}

#define MAX_NUM_OF_ELEM 100
//此處宏定義代表集合最大元素數,因為bitset的模板參數只能使用常量,所以此處用宏定義

void funPowerSet(int * b, int iSetLen)
{
	bitset<MAX_NUM_OF_ELEM+1> it;
	bitset<MAX_NUM_OF_ELEM+1> itEnd;
	itEnd[iSetLen]=1;
	for ( ; it!=itEnd; add1(it) )
	{
		cout << "{";
		for (uint64_t j = 0; j < iSetLen; j++)
		{
			if (it[j])
				cout << b[j] << ", ";
		}
		cout << "}\n";
	}
}

用遞歸實現位運算思路,也沒有元素數量限制。實現代碼如下:

#include <iostream>
using namespace std;

template<class T>
void powerSet(T list[], int k, int len)
{
	static bool * isNo = new bool[len];
	if (k == len - 1)
	{
		for (int i = 1; i >= 0; i--)
		{
			isNo[k] = !i;
			cout << "{";
			for (int i = 0; i < len; i++)
				if (isNo[i])
					cout << list[i] << ",";
			cout << "}\n";
		}
		return;
	}
	isNo[k] = 0; powerSet(list, k + 1, len);
	isNo[k] = 1; powerSet(list, k + 1, len);
}

int main()
{
	powerSet("abc", 0, 3);
}


以上為個人理解,可能有偏頗疏漏,歡迎交流指正。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM