1. 程式人生 > >位運算的應用:集合運算

位運算的應用:集合運算

問題:如何通過位運算求兩個集合的交集並集以及對稱差呢?

執行截圖:


其實很簡單,步驟如下:

①將所有可能出現的元素從1~n編上號

這裡我們假設所有可能的元素為'0'~'9','A'~'Z','a'~'z'

則編號為'0'~'9':0~9  'A'~'Z':10~35  'a'~'z':36~61

②利用一個整數儲存一個集合的資訊

C++中long long型別佔有64個位元位,第i個位元位就表示了對應字元的有無:1代表有,0代表無

③利用兩個整數的位運算即可表示相應集合的運算

"集合的交" --- (a & b)

"集合的並" --- (a | b)

"集合的差" --- a & (~b)


"集合的對稱差" ---  (a | b) & (~(a&b))


④根據整數的運算結果反寫出集合的運算結果即可

注意:系統預設只支援32位的移位運算,因此將1左移32位以上時:

1 << 40(×)

long long one = 1; one << 40; (√)

C++11程式碼如下:

/*C++11*/
#include <iostream>
#include <string>
#include <cctype>
using namespace std;
//改進1:將字元操作改為string操作

//'0'~'9':0~9  'A'~'Z':10~35  'a'~'z':36~61
char getKey(int i)
{
	if (i <= 9) return '0' + i;
	else if (i <= 35) return 'A' + i - 10;
	else return 'a' + i - 36;
}

//從字串中得到64位的位元串 
long long input()
{
	string a;
	cin >> a;
	long long tmp = 0, one = 1;
	for (auto p : a)
	{
		//改進2:判斷'0'~'9'/'A'~'Z'/'a'~'z'時運用isnum(),isupper(),islower()函式 
		if (isdigit(p)) tmp |= one << (p - '0');
		else if (isupper(p)) tmp |= one << (p - 'A' + 10);
		else if (islower(p)) tmp |= one << (p - 'a' + 36);
	}
	return tmp;
}

//相應的字元集合 
string output(long long a)
{
	string tmp = "{";
	long long one = 1;
	for (int i = 0; i <= 61; ++i)
	{
		if (a & (one << i))
			tmp = tmp + getKey(i) + ',';
	}
	if (*(tmp.end() - 1) == ',') *(tmp.end() - 1) = '}';
	else tmp += '}';
	return tmp+"\n";
}

//笛卡兒積 
string outputDsc(long long a, long long b)
{
	string tmp;
	long long one = 1;
	for (int i = 0; i <= 61; ++i)
		for (int j = 0; j <= 61; ++j)
			if ((a&(one << i) && (b&(one << j))))
				tmp = tmp + '<' + getKey(i) + ',' + getKey(j) + '>' + ',';
	if (!tmp.empty()) tmp.erase(tmp.end() - 1, tmp.end());
	return '{'+tmp+"}\n";
}

int main()
{
	long long a = 0, b = 0;
	cout << "輸入集合A:";
	a = input();
	cout << "輸入集合B:";
	b = input();

	//改進3:使用位運算代替雙重for迴圈查詢 
	cout << "集合A:" << output(a);
	cout << "集合B:" << output(b);
	cout << "集合的交:" << output(a & b);
	cout << "集合的並:" << output(a | b);
	cout << "集合的差:" << output(a & (~b));
	cout << "集合的對稱差:" << output((a | b) & (~(a&b)));
	cout << "集合的笛卡爾積:" << endl << outputDsc(a, b);
	system("pause");
	return 0;
}

謝謝觀看~