IntSet integer collection
13.3 IntSet collection of integers
13.3.1 ADT(C#)
-
Encapsulating a class with an interface is equivalent to only opening part of the functions of the class
eg:
public interface ISet_my<T> { uint[] GetCoordinate(T element); uint[] Add(T element); //加入元素element,返回offset uint[] Remove(T element); //bool IsMember(T element); string GetBinString(); //get 二进制流,其实还是string流而不是bitString string PrintBinString(); //返回BinString string GetIntString(); //返回intString string PrintIntString(); ISet_my<T> Union(ISet_my<T> ISet_2); //并集 ISet_my<T> Intersect(ISet_my<T> ISet_2); //交集 ISet_my<T> DiffSet(ISet_my<T> ISet_2); //差集 ISet_my<T> Complement(); //补集 }
13.3.2 Core idea
The core idea of IntSet (integer set) is to compress the set to store more data, such as:
Use one int32 space to store 32 ints
Compared with using 32 int32 spaces to store 32 ints, the overhead of IntSet is instantly smaller, right?
13.3.2 Implementation Principle
-
bitMap (bitmap) and GetCoordinate()
public class IntSet_my : ISet_my <uint>
{
//member
private readonly uint[] _bitMap; //_bitMap的比特流表示IntSet存储信息
public uint _bitSize { get; } //_bitMap的比特流占多少位二进制
//contributor
public IntSet_my(uint bitSize_0)
{
_bitSize = bitSize_0;
_bitMap = new uint[_bitSize / 32 + 1]; //at lease 1 int32 to store IntSet
for (int i = 0; i < _bitMap.Length; i++) //initialize IntSet as null
_bitMap[i] = 0;
}
//get ( index_bitMap, index_bit )
public uint[] GetCoordinate(uint e)
{
uint[] coordiante = new uint[2]; //二元坐标
if (e > _bitSize) //e不在
throw new ArgumentOutOfRangeException();
coordiante[0] = e / 32; // bitMap index
coordiante[1] = e % 32; // bit index in bitMap[ coordiante[0] ]
return coordiante;
}
- Add() and Remove()
//add int to IntSet
public uint[] Add( uint e )
{
uint[] coordi = GetCoordinate( e ); //get coordinate
_bitMap[coordi[0]] |= (uint)Math.Pow(2, coordi[1]); //add
return coordi; //return index
}
//remove int from IntSet
public uint[] Remove(uint e)
{
uint[] coordi = GetCoordinate(e); //get coordinate
_bitMap[coordi[0]] &= (~coordi[1]); //remove
return coordi; //return index
}
- GetBinString() gets a binary string and GetIntString gets an integer string
public string GetBinString()
{
string binString = string.Empty; //null string
for (int i = 0; i < _bitMap.Length;) //each _bitMap[]
{
//10进制int->2进制int->2进制string, 并在左侧补齐到32位2进制
binString = Convert.ToString(_bitMap[i++], 2).PadLeft(32, '0') + binString; //补0方便之后输出!
}
return binString;
}
public string PrintBinString()
{
string result = GetBinString(); //get binString
Console.WriteLine("\n从右往左, 第0位为表示0的二进制位\n");
for (int i = result.Length - 1; i >= 0; ) //each _bitMap[]
{
//print binString
for(int k = 0; k < 4; k++) //each 4 bit intervene " "
Console.Write(result[i--]);
Console.Write(" ");
}
Console.Write("\n");
return result;
}
public string GetIntString()
{
string binString = this.GetBinString();
string intString = string.Empty;
for (int i = binString.Length - 1, j = 0; i >= 0; j++) //each _bitMap[]
{
//print IntString
if (binString[i--] == '1')
intString += " " + Convert.ToString(j);
}
return intString;
}
public string PrintIntString()
{
string result = this.GetIntString(); //get binString
Console.Write("\nIntSet中元素升序排列: {0} \n", result);
return result;
}
- Union(), Intersect(), Differ()
- The unit for intersection, union, and complement operations is bitMap[]!
(though fundamentally a bit in a computer) - Encapsulate with interface!
//Intersect
public IntSet_my Intersect(IntSet_my IntSet_2)
{
IntSet_my IntersectSet;
IntersectSet = new IntSet_my(this._bitSize < IntSet_2._bitSize ?
this._bitSize : IntSet_2._bitSize); //交集大小取小的集合大小
for (int i = 0; i < IntersectSet._bitMap.Length; i++) // IntersectSet[0~IntSet_2.bitSize) = union
IntersectSet._bitMap[i] = this._bitMap[i] & IntSet_2._bitMap[i]; //运算为&, 实质上是int32->二进制&->int32
return IntersectSet;
}
//Differ
public IntSet_my Differ(IntSet_my IntSet_2)
{
IntSet_my DifferSet = new IntSet_my(_bitSize);
int differ_Size = _bitMap.Length < IntSet_2._bitMap.Length ? this._bitMap.Length : IntSet_2._bitMap.Length;
for (int i = 0; i < differ_Size; i++) // DifferSet[0~_bitMap.Length) = Differ
DifferSet._bitMap[i] = _bitMap[i] & (~IntSet_2._bitMap[i]);
return DifferSet;
}
//Complement
public IntSet_my Complement()
{
IntSet_my CompliSet = new IntSet_my(_bitSize);
for (uint i = 0; i < _bitMap.Length; i++) // CompliSet[0~IntSet_2.bitSize) = Compli
CompliSet._bitMap[i] = ~this._bitMap[i];
return CompliSet;
}
//接口
ISet_my<uint> ISet_my<uint>.Union(ISet_my<uint> ISet_2)
{
return Union(ISet_2 as IntSet_my);
}
ISet_my<uint> ISet_my<uint>.Intersect(ISet_my<uint> ISet_2)
{
return Intersect(ISet_2 as IntSet_my);
}
ISet_my<uint> ISet_my<uint>.DiffSet(ISet_my<uint> ISet_2)
{
return Differ(ISet_2 as IntSet_my);
}
ISet_my<uint> ISet_my<uint>.Complement()
{
return Complement();
}
13.3.3 Problems encountered and lessons learned
-
The Convert method does not understand
When converting decimal int to binary int, I have been thinking about converting it into a computer bit, but I don’t know how to achieve it
for example:
Convert.ToBase64CharArray( Byte[] inArray, Int32 offsetIn, Int32 length, Char[] outArray, Int32 offsetOut)
- inArray is the 8-bit unsigned integer array to be converted
- offsetIn is the starting index of inArray conversion part
- length is the length of inArray conversion part
- outArray is the character array to output
- offsetOut is the starting index of the character array to be output
ToBase64 only supports int8, and the storage unit of bitMap is int32.
This seems to be the only way to accumulate...
-
When designing, the print function and the getValue function should be separated
-
The intersection, difference, and complement sets are all calculated in units of int32 array elements
-
string == ‘1’Instead of string == "1" or string == 1 ! ! !
-
In VS, how to convert int into string
- You can’t brute force to char, eg: (char) j, so ASCII and Unicode encoding are not compatible, and it will be garbled
- Only the string converted to Unicode, eg: Conver.ToString(j)
13.3.4 Issues that still need to be resolved
- How to use the generic interface???
- Unicode, ASCII, Utf-8 encoding difference