• 谈谈Set这件小事


    Set就是集合类型,最常见用操作就是判有判无。

    常见的底层实现有位向量实现和有序链表实现。

    有序链表很简单,双指针撸到底,这里不详细讲。下面我们谈谈java实现位向量。

    不止java,C++中也没有直接的位操作。所以想把整数类型映射到一个bit位上,我们要自己定义操作。

    C++比较方便的是有unsigned类型。在unsigned 上左移右移都补0。

    可java没有unsigned类型。这就麻烦了。如果我们定义short[] 作为位向量 是肯定会出现错误的。

    虽然java有额外的>>>移位,右移始终补0。但对于short,它会先将short转为int,再移位,最后再截短赋值。这就会出现错误。

    由于short 16bit, int 32bit,演示过于麻烦。我们将其截半,结果是一样的。

    比如-1, 8bit 表示 1111 1111 如果>>>2 移位, 我们期望的结果是 0011 1111。

    但实际上 -1 会先转为16位: 1111 1111 1111 1111, 再移位: 0011 1111 1111 1111, 最后截短赋值: 1111 1111。

    看,本来我们期望结果是0011 1111,但实际上却是1111 1111。这对于我们实现值位映射是不利的。

    所以用java实现位向量,不可用short[],直接用int[],不可用算术右移>>, 直接用逻辑右移>>>。这样就没问题了。

    这样的话,一个int可以存放32个元素的有无信息,充分利用了存储空间。

    看,java也可以如此底层。

    至于集合的交,并,差等,可以用位运算& | ~ 等实现。最最核心的代码时实现值位存取映射。

    下面给出代码:

    public class BitSet {
        private int setSize; // setSize is the element number of set
        private int vectorSize; // vectorSize is the storage that needed by the set
        private int[] bitVector;
    
        public BitSet(){
            this.setSize = 1000;
            this.vectorSize = (this.setSize + 31) >> 5;
            this.bitVector = new int[this.vectorSize];
        }
    
        /**
         * set the volume of the set
         * @param setSize the volume of the set
         */
        public BitSet(int setSize){
            this.setSize = setSize;
            this.vectorSize = (setSize + 31) >> 5;
            this.bitVector = new int[this.vectorSize];
        }
    
        /**
         * set member value.Note that the min member should be 1, not 0.
         * @param element the element of set
         * @param value the value to set; only 0 or 1
         * @return true or false
         */
        public boolean setMemberValue(int element, int value){
            if (element < 1 || element > setSize){
                System.err.println("Out of Range!");
                return false;
            }
            element -= 1;        // begin with 0 instead of 1.
            int id = element / 32;
            int ad = element % 32;
            int tmp = bitVector[id];
            int last = tmp >>> (31 - ad);
            tmp = tmp << (ad + 1);
            if (last % 2 == 0 && value == 1){
                last = last + 1;
            }
            if (last % 2 == 1 && value == 0){
                last -= 1;
            }
            bitVector[id] = (last << (31 - ad)) | (tmp >>> (ad + 1));
            return  true;
        }
    
        /**
         * get the value of the element. Note that the min element is 1, not 0;
         * @param element
         * @return if the element in the set, return 1; else 0.
         */
        public int getMemberValue(int element){
            if (element < 1 || element > setSize){
                System.err.println("Out Of Range!");
                return -1;
            }
            element -= 1;
            int id = element / 32;
            int ad = element % 32;
            int result = bitVector[id] >>> (31-ad);
            result %= 2;
            return result;
        }
    
        /**
         * add the element to the set
         * @param element
         * @return
         */
        public boolean addMember(int element){
            if (getMemberValue(element) == 1){
                System.err.println("Already In!");
                return false;
            }
            return setMemberValue(element,1);
        }
    
        /**
         * delete the element of the set
         * @param element
         * @return
         */
        public boolean delMember(int element){
            if (getMemberValue(element) == 0){
                System.err.println("Not have it!");
                return false;
            }
            return setMemberValue(element,0);
        }
    
        /**
         * print an int in binary string, from the first bit that not 0.
         * @param value
         */
        public void printBinaryValue(int value){
            System.out.println(Integer.toBinaryString(value));
        }
    
        public static void main(String[] args) {
    	// write your code here
            BitSet bitSet = new BitSet(5000);
            bitSet.addMember(1);
            bitSet.addMember(31);
            bitSet.addMember(20);
            bitSet.addMember(32);
            bitSet.addMember(2);
            bitSet.printBinaryValue(bitSet.bitVector[0]);
            bitSet.addMember(21);
            bitSet.printBinaryValue(bitSet.bitVector[0]);
            bitSet.delMember(21);
            bitSet.printBinaryValue(bitSet.bitVector[0]);
            System.out.println(bitSet.getMemberValue(1));
            System.out.println(bitSet.getMemberValue(20));
        }
    }
    

      

  • 相关阅读:
    快速幂&欧拉降幂
    欧拉函数
    素数打表-筛法
    多源最短路径问题(Floyd算法)
    蓝桥杯-本质上升序列
    蓝桥杯-玩具蛇
    SDUT-计算机组成原理
    取消U盘和移动硬盘的GPT保护分区
    Windows 10 上运行 photoshop 等软件出现 loadlibrary failed with error 87 的解决方法!
    做题笔记
  • 原文地址:https://www.cnblogs.com/zqiguoshang/p/6559717.html
Copyright © 2020-2023  润新知