目录
2_用位向量实现集合(附实现代码☟)
1_集合
1.1_集合的定义
集合是表示事物的最有效的数学工具之一。
集合是由元素(成员)组成的一个类。集合的成员可以是一个集合,也可以是一个原子。
同一个元素在一个集合中不能多次出现。
有时需要表示有重复元素的集合,这时允许同一个元素在集合中多次出现。这样的集合称为多重集合。
1.2_集合的记号
当集合中的原子具有线性序关系(或称全序关系)“<”时,称集合为有序集(全序集或线性序集)。“<”是集合的一个线性序,它有如下性质:
- 若a,b是集合中任意两个原子,则a<b,a=b和b<a三者必居其一。
- 若a,b和c是集合中的原子,且a<b,b<c,则a<c**(传递性)**。
- 将集合的元素称为记录,每个记录有多个项(或域)来表示元素的各种属性。
- 通过键值可以唯一地确定集合中的一个元素。
- 键只是元素记录中许多域中的一个。
- 集合中元素的列举顺序是任意的,如{1,3}和{3,1}表示同一个集合。
- 关于集合的最基本的运算是并、交、差运算。
- 设A和B是两个集合。
- 把他们所有的元素合并在一起组成的集合,叫做集合A与集合B的并集,记作A∪B,读作A并B。
- 由所有属于集合A且属于集合B的元素所组成的集合,叫做集合A与集合B的交集,记作A∩B。
- 则所有属于A且不属于B的元素构成的集合,叫做集合A减集合B(或集合A与集合B之差),类似地,对于集合A、B,把集合{x∣x∈A,且x∉B}叫做A与B的差集。例如:
- A={1,2,3},B={2,4},则A-B={1,3}。
1.3_定义在集合上的基本运算
约定:其中大写字母表示一个集合,小写字母表示集合中的一个元素
- Set_Union(A, B):并集运算
- Set_Intersection(A, B):交集运算
- Set_Difference(A, B):差集运算
- Set_Assign(A, B):赋值运算(将B的元素赋给A)
- Set_Equal(A, B):判等运算
- Set_Member(A, B):成员运算
- Set_Insert(x, S):插入运算
- Set_Delete(x, S):删除运算
2_用位向量实现集合
- 位向量是一种每个元素都是二进制位(即0/1值)的数组
位向量实现的集合结构Bitset定义
typedef struct bitset *Set; /* 位向量集合指针类型 */
typedef struct bitset {
int setSize; /* 集合大小 */
int arraySize; /* 位数组大小 */
unsigned short* v; /* 位数组 */
}Bitset;
创建一个用位向量实现、可存储集合大小为size的空集
Set SetInit(int size)
{
Set S = (Set)malloc(sizeof * S);
S->setSize = size;
/* 存储大小为setsize的集合所需的无符号短整数位数 */
S->arraySize = (size + 15) >> 4;
S->v = (unsigned short*)malloc(size * sizeof(unsigned short));
/* 初始化为空集 */
for (int i = 0; i < size; i++) S->v[i] = 0;
return S;
}
通过复制表示集合的位向量来实现赋值运算
void SetAssign(Set A, Set B)
{
/* 集合赋值运算 */
if (A->arraySize != B->arraySize) return;
for (int i = 0; i < A->arraySize; i++) A->v[i] = B->v[i];
}
通过检测元素在表示集合的位向量中相应的位来判断成员的属性
int SetMember(int x, Set S)
{
/* 成员属性判断 */
if (x < 0 || x > S->setSize) return 0;
return S->v[ArrayIndex(x)] & BitMask(x);
}
下标定位函数
int ArrayIndex(int x)
{
/* 右移4位获得x在数组中的位置*/
return x >> 4;
}
/* 位屏蔽函数*/
unsigned short BitMask(int x)
{
/* 确定x在相应数组单元中的准确位置 */
return 1 << (x & 15);
}
/* 判断集合相等函数 */
int SetEqual(Set A, Set B)
{
/* 判断集合A和集合B是否相等*/
if (A->arraySize != B->arraySize) return 0;
int retval = 1;
for(int i = 0; i < A->arraySize; i ++ )
if (A->v[i] != B->v[i]) {
retval = 0;
break;
}
return retval;
}
/* 并集运算 */
Set SetUnion(Set A, Set B)
{
Set tmp = SetInit(A->setSize);
for (int i = 0; i < A->arraySize; i++)
tmp->v[i] = A->v[i] | B->v[i];
return tmp;
}
/* 交集运算 */
Set SetIntersection(Set A, Set B)
{
Set tmp = SetInit(A->setSize);
for (int i = 0; i < A->arraySize; i++)
tmp->v[i] = A->v[i] & B->v[i];
return tmp;
}
/* 差集运算 */
Set SetDifference(Set A, Set B)
{
Set tmp = SetInit(A->setSize);
for (int i = 0; i < A->arraySize; i++)
tmp->v[i] = A->v[i] ^ B->v[i];
return tmp;
}
/* 元素插入运算 */
void SetInsert(int x, Set S)
{
if (x < 0 || x >= S->setSize) return;
S->v[ArrayIndex(x)] |= ~BitMask(x);
}
/* 元素删除运算 */
void SetInsert(int x, Set S)
{
if (x < 0 || x >= S->setSize) return;
S->v[ArrayIndex(x)] &= ~BitMask(x);
}