整数集合
背景
今天复习整数集合这种数据结构,这种数据结构是由存储权限而来的。
基本理论
含义
整数集合实质上是一个二进制串,他代表用户对于一连串功能的权限情况,若某位为1,代表具有该权限;若某位为0,代表不具有该权限。
而在存储的时候,我们利用一个无符号整型数组来存储这个二进制串,数组中每一个元素都是一个32位无符号整型,这一个元素代表一个32位的二进制串,也就代表32个功能的权限情况。
理解这种数据结构的关键在于从权限的角度出发去理解。
整数集合的操作
- 向集合中添加元素(添加权限)
- 删除集合中的元素(删除权限)
- 判断元素是否属于该集合
- 得到集合中的所有元素(获取具有权限的功能)
- 求两个集合的并集
- 求两个集合的交集
- 求两个集合的差集
- 求集合的补集
代码实现
- 首先定义整数集合所能进行的操作
public interface ISet<T, TK>
{
void Insert(T elt); // 添加新元素
void Remove(T elt); // 删除元素
string GetElements(); // 得到集合中的所有元素
bool IsMember(T elt); // 判断是否含有该元素
TK Complement(); // 做补运算
TK Union(TK set); // 并
TK Diff(TK set); // 差
TK Intersect(TK set); // 交
}
- 具体代码实现:
/// <summary>
/// 整数集合实现
/// 整数数组是由权限的应用得到的一种数据结构,理解的时候从权限(二进制串)的角度去理解
/// 如: 一个整数数组表示 对于若干功能,一个用户所有的权限情况,并对权限进行操作,如添加权限,删除权限
/// 整数数组间的运算 即 不同用户的权限 之间的运算
/// </summary>
namespace IntSetStructure
{
public class IntSet : ISet<uint, IntSet>
{
// 数组中的一个32位整型,代表有32个功能,0表示无权限,1表示有权限
// 一个32位整型有32位可以表示32个权限
private readonly uint[] _bitSet;
//使用uint,使所有位数表示数值,没有符号位
/// <summary>
/// MaxRange代表整数数组所代表的二进制串的最大位数,即存储的权限个数
/// </summary>
public uint MaxRange { get; }
/// <summary>
/// 整数数组的构造函数
/// </summary>
/// <param name="maxrange">整数数组表示的二进制串的最大位数</param>
public IntSet(uint maxrange)
{
if (maxrange < 0)
throw new ArgumentOutOfRangeException();
MaxRange = maxrange;
_bitSet = new uint[MaxRange / 32 + 1]; //一个整数代表32位
for (int i = 0; i < _bitSet.Length; i++)
{
_bitSet[i] = 0;
}
}
/// <summary>
/// 获取对应位数elt在整数数组中的索引,我们要操作的权限对应的整数在数组中的索引
/// </summary>
/// <param name="elt"></param>
/// <returns></returns>
public uint ArrayIndex(uint elt) // elt即第elt个功能
{
if (elt > MaxRange)
throw new ArgumentOutOfRangeException();
return (uint)elt / 32;
}
// 返回elt对应的整型值
/// <summary>
/// 获取elt表示的二进制串,elt其实就是一个权限
/// </summary>
/// <param name="elt">代表一个功能</param>
/// <returns>只有一位为1的二进制串,表示elt对应的权限</returns>
public uint BitMask(uint elt)
{
if (elt > MaxRange)
throw new ArgumentOutOfRangeException();
return (uint)Math.Pow(2, elt % 32);
}
/// <summary>
/// 向集合添加元素,本质为对elt对应的功能授予权限
/// </summary>
/// <param name="elt"></param>
public void Insert(uint elt)
{
if (elt > MaxRange)
throw new ArgumentOutOfRangeException();
_bitSet[ArrayIndex(elt)] |= BitMask(elt);
}
/// <summary>
/// 从集合中删除元素,本质为对elt对应的功能撤回权限
/// </summary>
/// <param name="elt">对应的第elt个功能</param>
public void Remove(uint elt)
{
if (elt > MaxRange)
throw new ArgumentOutOfRangeException();
_bitSet[ArrayIndex(elt)] &= ~BitMask(elt);
}
/// <summary>
/// 判断是否具有elt功能的权限
/// </summary>
/// <param name="elt">功能</param>
/// <returns>true代表具有该功能的权限,false反之</returns>
public bool IsMember(uint elt)
{
if (elt > MaxRange)
throw new ArgumentOutOfRangeException();
uint i = _bitSet[ArrayIndex(elt)] & BitMask(elt);
return i != 0;
}
/// <summary>
/// 得到有权限的功能
/// </summary>
/// <returns></returns>
public string GetElements()
{
string s = GetBitString();
string str = string.Empty;
int j = 0;
for (int i = s.Length - 1; i >= 0; i--)
{
if (s[i] == '1')
str += j + " ";
j++;
}
return str.Trim();
}
/// <summary>
/// 将整数数组转换为二进制串
/// </summary>
/// <returns>整数数组代表的二进制串</returns>
public string GetBitString()
{
string str = string.Empty;
for (int i = 0; i < _bitSet.Length; i++)
{
str = Convert.ToString(_bitSet[i], 2).PadLeft(32,'0') + str;
// Convert.ToString转换为二进制,PdfLeft补足为32位
}
return str.Remove(0, 32 - (int)(MaxRange % 32 + 1));
}
/// <summary>
/// 数组间进行并运算
/// </summary>
/// <param name="set"></param>
/// <returns></returns>
public IntSet Union(IntSet set)
{
if (set == null)
throw new Exception("Union操作集合为null");
if (MaxRange != set.MaxRange)
throw new Exception("两集合长度不同,不能运算");
IntSet temp = new IntSet(MaxRange);
for (int i = 0; i < _bitSet.Length; i++)
{
temp._bitSet[i] = _bitSet[i] | set._bitSet[i];
}
return temp;
}
/// <summary>
/// 数组间进行差运算
/// </summary>
/// <param name="set"></param>
/// <returns></returns>
public IntSet Diff(IntSet set)
{
if (set == null)
throw new Exception("Diff操作集合为null");
if (MaxRange != set.MaxRange)
throw new Exception("不符合差运算规则");
IntSet temp = new IntSet(MaxRange);
for (int i = 0; i < _bitSet.Length; i++)
{
temp._bitSet[i] = _bitSet[i] & (~set._bitSet[i]);
}
return temp;
}
/// <summary>
/// 补运算
/// </summary>
/// <returns></returns>
public IntSet Complement()
{
IntSet temp = new IntSet(MaxRange);
for (int i = 0; i < _bitSet.Length; i++)
{
temp._bitSet[i] = ~_bitSet[i];
}
return temp;
}
/// <summary>
/// 数组间进行交运算
/// </summary>
/// <param name="set"></param>
/// <returns></returns>
public IntSet Intersect(IntSet set)
{
if (set == null)
throw new Exception("Intersect操作集合为null");
if (MaxRange != set.MaxRange)
throw new Exception("不符合Intersect运算规则");
IntSet temp = new IntSet(MaxRange);
for (int i = 0; i < _bitSet.Length; i++)
{
temp._bitSet[i] = _bitSet[i] & set._bitSet[i];
}
return temp;
}
/// <summary>
/// 判断两整数集合 是否相等
/// </summary>
/// <param name="B"></param>
/// <returns></returns>
public bool IsEqual(IntSet B)
{
if (B == null)
throw new ArgumentNullException();
string bitStringA = GetBitString();
string bitStringB = B.GetBitString();
if (bitStringA == bitStringB)
return true;
return false;
}
/// <summary>
/// 判断 传入整数集合 是否为该整数集合的子集
/// </summary>
/// <param name="B"></param>
/// <returns></returns>
public bool IsSubSet(IntSet B)
{
if (B == null)
throw new ArgumentNullException();
string bitStringA = GetBitString();
string bitStringB = B.GetBitString();
if (bitStringA.IndexOf(bitStringB) != -1)
return true;
return false;
}
}
}
throw new ArgumentNullException();
string bitStringA = GetBitString();
string bitStringB = B.GetBitString();
if (bitStringA.IndexOf(bitStringB) != -1)
return true;
return false;
}
}
}