二进制自问世以来.在计算机的研究和应用领域起着重要的作用,它的值域只有⋯0’,⋯1’两个值,但是通过对这两个值的有效组合和简单运算,却能表达出客观真实世界的千变万化,下面通过分析二进制和集合之间强大的内在联系,说明二进制在集合运算中的巨大作用。若集合A具有n个元素,则A 的所有子集(幂集)的个数IP(A)1=2“,例如,A={0,6,c},则A的幂集为( ,fa},(6},(0,6},{c},{atc},{b,c},{atb,c}】,A的幂集的基数为2 =8。长度为n的二进制位所能表达的数据个数为2“.例如长度为3的二进制位,所能生成的数据为000,001,010,0l1.100.101,l10,l11,共2 =8个数据。
通过比较发现,长度为n的二进制位所能表达的数据个数和具有相同元素个数的集合的所有子集(幂集)的数目相同,由此可以猜想二进制和集合之间应该具有某些联系,现在做以下
规定:规定阎:对于集合,_ ,‘ ,‘:,⋯ ,‘ },规定一个n位的二进制数P=f7r 7r ⋯7r。7r。}与之对应,其中二进制数的第0位7r。对应集合的第0个元素‘ ,第1位7r 对应第1个元素‘.,第k位对应第k个元素‘ 。
例如.规定一个3位的二进制数,用此二进制数的第0位代表上面所提到的集合 的a元素,第1位代表集合 的b元素,第2位代表集合 的C元素.然后比较集合 的幂集和
二进制数据的关系,如图1所示。
通过比较发现.如果我们按照图1中的对应关系对子集进行编号,则集合第 个子集和二进制所产生的第 个数据之间存在着非常微妙的对照关系:如果在子集中某个元素存在,则
此子集对应的二进制数中该元素所对应的二进制位为1.否则为0。例如,子集fa,b},因为a对应二进制第0位,b对应二进制第1位,C对应二进制的第三位.而C元素没有在子集中出现.所以其对应的二进制数为011。
【DEF12】子集的下标:集合 的子集所对应的二进制数的十进制数值称为此子集的下标。有了集合与二进制之间的这种内在联系,以后在对集合操作时,我们没有必要对子集中的实际元素进行处理.只要知道子集的下标.就可以很容易地利用位运算来实现对集合进行各种操作的目的。
用二进制求集合的幂集
已知集合 ,求 的幂集。由于集合子集中的元素与子集下标中二进制位的“1”相对应,因此求子集中元素的运算可以转化为寻找子集下标二进制位中“1”所在位置的运算.此运算可以利用移位操作来实现。例如.求101所对应的 的子集,我们可以通过3次移位,每次先将当前的数值与数值1相与,如果结果等于1,则本次第0位上的值为1,否则为0.由移位的次数可以知道当前第0位的1在原数据中的位置.从而找到对应的实际元素。运算如下:
{
int f, j;
/*f标志当前输出是否为子集的第一个元素,j记录移位次数*/
f=o;
prinf("{");
while(b>0)
(if((b&1)>O)
if( f==0)
}
else
pfinf(”,%c”,A[j]);
b=b>>1:
j=j+l;
)
通过比较发现,长度为n的二进制位所能表达的数据个数和具有相同元素个数的集合的所有子集(幂集)的数目相同,由此可以猜想二进制和集合之间应该具有某些联系,现在做以下
规定:规定阎:对于集合,_ ,‘ ,‘:,⋯ ,‘ },规定一个n位的二进制数P=f7r 7r ⋯7r。7r。}与之对应,其中二进制数的第0位7r。对应集合的第0个元素‘ ,第1位7r 对应第1个元素‘.,第k位对应第k个元素‘ 。
例如.规定一个3位的二进制数,用此二进制数的第0位代表上面所提到的集合 的a元素,第1位代表集合 的b元素,第2位代表集合 的C元素.然后比较集合 的幂集和
二进制数据的关系,如图1所示。
序号 | 集合 | 对应二进制 |
0 | φ | 000 |
1 | (a) | 001 |
2 | (b) | 010 |
3 | {αb} | 011 |
4 | (c) | 100 |
5 | {α .c} | 101 |
6 | (b .c) | 110 |
7 | {αb .c} | 111 |
此子集对应的二进制数中该元素所对应的二进制位为1.否则为0。例如,子集fa,b},因为a对应二进制第0位,b对应二进制第1位,C对应二进制的第三位.而C元素没有在子集中出现.所以其对应的二进制数为011。
【DEF12】子集的下标:集合 的子集所对应的二进制数的十进制数值称为此子集的下标。有了集合与二进制之间的这种内在联系,以后在对集合操作时,我们没有必要对子集中的实际元素进行处理.只要知道子集的下标.就可以很容易地利用位运算来实现对集合进行各种操作的目的。
用二进制求集合的幂集
已知集合 ,求 的幂集。由于集合子集中的元素与子集下标中二进制位的“1”相对应,因此求子集中元素的运算可以转化为寻找子集下标二进制位中“1”所在位置的运算.此运算可以利用移位操作来实现。例如.求101所对应的 的子集,我们可以通过3次移位,每次先将当前的数值与数值1相与,如果结果等于1,则本次第0位上的值为1,否则为0.由移位的次数可以知道当前第0位的1在原数据中的位置.从而找到对应的实际元素。运算如下:
① 第0次与:101&O01:l,a对应二进制位的第0位,而且本次相与的结果为1.所以a属于此子集:101右移一位,现在的数值为010。
② 第1次与:OlO&O01=0,b对应二进制位的第1位.而且本次相与的结果为0,所以b不属于此子集。010右移一位,现在的数值为001。
③第1次与:O01&O01=1.C对应二进制位的第2位.而且本次相与的结果为1,所以C属于此子集。001右移一位,现在的数值为000。
计算完毕。求出101对应的 的子集为 ,c}。
求子集元素的C语言算法程序如下:
findelement找出集合A 中子集下标b所对应的子集中的所有元素 /
{
int f, j;
/*f标志当前输出是否为子集的第一个元素,j记录移位次数*/
f=o;
prinf("{");
while(b>0)
(if((b&1)>O)
if( f==0)
{
f=1;
pfinf(”%c”,A[j]);}
else
pfinf(”,%c”,A[j]);
b=b>>1:
j=j+l;
)
prinf("}");
若求A的所有子集.只要从子集下标0~2⋯依次求各对应子集的元素即可.本算法可用一个循环完成,代码如下:
void findchildsets(char A[],unsigned n)
/*n为A的子集个数*/
{unsigned i;
for(i=0;i< n;i++)
findelement(A,i);
}