天天看點

資料結構學習手冊——IntSet 整數集合13.3 IntSet 整數集合

IntSet 整數集合

  • 13.3 IntSet 整數集合
    • 13.3.1 ADT(C#)
    • 13.3.2 核心思想
    • 13.3.2 實作原理
    • 13.3.3 遇到的問題及教訓
    • 13.3.4 仍需要解決的問題

13.3 IntSet 整數集合

13.3.1 ADT(C#)

  1. 用接口封裝類,相當于隻開放類的部分功能

    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 核心思想

​ IntSet (整數集合) 的核心思想就是壓縮集合存儲更多資料,比如:

用一個int32空間 存32個int

比起用32個int32空間 存32個int,IntSet的開銷瞬間就小了是不是!

13.3.2 實作原理

  1. bitMap(位圖) 和 GetCoordinate()
    資料結構學習手冊——IntSet 整數集合13.3 IntSet 整數集合
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;
        }
           
  1. Add()和Remove()
資料結構學習手冊——IntSet 整數集合13.3 IntSet 整數集合
//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
        }
           
  1. GetBinString()擷取二進制字元串和 GetIntString 擷取整數字元串
資料結構學習手冊——IntSet 整數集合13.3 IntSet 整數集合
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;
        }
           
資料結構學習手冊——IntSet 整數集合13.3 IntSet 整數集合
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;
        }
           
  1. Union(), Intersect(), Differ()
  • 進行交、并、補運算的機關是bitMap[] !

    (雖然根本上是 計算機中的bit )

  • 用接口封裝!
//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 遇到的問題及教訓

  1. Convert方法不了解

    在10進制int轉二進制int時一直想着要轉成計算機bit,但不知道要用什麼方法實作

    比如:

    Convert.ToBase64CharArray( Byte[] inArray, Int32 offsetIn, Int32 length, Char[] outArray, Int32 offsetOut)

    • inArray 為要轉化的 8-bit unsigned integer 數組
    • offsetIn 為 inArray轉化部分的起始索引
    • length 為 inArray轉化部分的長度
    • outArray 為要輸出的字元數組
    • offsetOut 為要輸出的字元數組的起始索引

    ToBase64隻支援int8,bitMap的存儲機關是int32。

    這個好像隻能靠積累了…

  2. 設計時,print功能和getValue功能要分開
  3. 交集差集補集合都是以int32 數組元素為機關計算
  4. string == ‘1’ 而不是 string == “1” 或者 string == 1 !!!
  5. 在VS裡,int 如何轉化加入string
    • 不能暴力轉char ,eg: (char) j, 這樣ASCII和Unicode編碼不相容,會亂碼
    • 隻有轉成Unicode的string,eg: Conver.ToString(j)

13.3.4 仍需要解決的問題

  1. 泛型接口具體使用方法???
  2. Unicode, ASCII, Utf-8 編碼差別

繼續閱讀