排序8:位图排序

Posted 纵横千里,捭阖四方

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了排序8:位图排序相关的知识,希望对你有一定的参考价值。

位图排序也称为bitmap排序,它主要用于海量数据去重和海量数据排序,假如说有10 亿个int类型且全部不相同的数据,给1G内存让你排序,你怎么排,如果全部加载到内 存中,相当于40亿个字节,大概约等于4G内存。所以全部加载到内存肯定不行,如果我 们使用位图排序的话,我们用long类型表示,一个long占用8个字节也就是64位,所以 如果我们使用位图排序的话只会占用约0.125G内存,内存占用大大减少。但位图排序有 个缺点就是数据不能有重复的,如果有重复的会覆盖掉,这也是位图能在海量数据中去 重的原因,我们看下位图排序的代码:

 public static int[] bitmapSort1(int[] arary) {
        int max = getMaxNumbit1(arary);
        int N = max / 64 + 1;
        long[] bitmap = new long[N];
        for (int i = 0; i < arary.length; i++)
            bitmap[arary[i] / 64] |= 1L << (arary[i] % 64);

        int k = 0;
        for (int i = 0; i < N; i++) {
            for (int j = 0; j < 64; j++) {
                if ((bitmap[i] & (1L << j)) != 0) {
                    arary[k++] = i * 64 + j;
                }
            }
        }
        if (k < arary.length) {
            return Arrays.copyOfRange(arary, 0, k);
        }
        return arary;
    }

    private static int getMaxNumbit1(int[] arary) {
        int max = arary[0];
        for (int i = 1, length = arary.length; i < length; i++) {
            if (arary[i] > max) {
                max = arary[i];
            }
        }
        return max;
    }

测试一下:

int array2[] = {2, 16, 97, 13, 15, 11, 89, 7, 63, 21, 66, 8, 0};
int array3[]= bitmapSort1(array2);
System.out.println(Arrays.toString(array3));

执行结果:

 我们看到这是使用的是位表示,一个long类型占8个字节,但他可以表示64个数字,所 以内存占用会大大减少。最后有个k < array.length的判断,是因为如果有重复的数据 会覆盖掉重复的,导致数组变小。但这里面还有个问题就是不能有负数出现,如果出现 负数会报异常,我们也可以改一下让负数也可以排序,看代码。

public static int[] bitmapSort2(int[] arary) {
        int []value = getMaxNumbit2(arary);
        int N = (value[0]-value[1]) / 64 + 1;
        long[] bitmap = new long[N];

        for (int i = 0; i < arary.length; i++)
            bitmap[(arary[i]-value[1]) / 64] |= 1L << ((arary[i]-value[1]) % 64);

        int k = 0;
        int []temp=new int[arary.length];

        for (int i = 0; i < N; i++) {
            for (int j = 0; j < 64; j++) {
                if ((bitmap[i] & (1L << j)) != 0) {
                    arary[k++] = i * 64 + j+value[1];
                }
            }
        }
        if (k < arary.length) {
            return Arrays.copyOfRange(arary, 0, k);
        }
        return arary;
    }
    
   private static int[] getMaxNumbit2(int[] arary) {
        int max = arary[0];
        int min = arary[0];
        for (int i = 1, length = arary.length; i < length; i++) {
            if (arary[i] > max) {
                max = arary[i];
            }else if(arary[i]<min){
                min=arary[i];
            }
        }
        return new int[]{max,min};
    }  

再测试一下:

 int array[] = {2, 6, 9, 3, 5, 1, -9, 7, -3, -1, -6, 8, 0};
 int array3[]= bitmapSort2(array);
 System.out.println(Arrays.toString(array3));

执行结果:

以上是关于排序8:位图排序的主要内容,如果未能解决你的问题,请参考以下文章

对大数据量进行排序--位图法

位图排序思想及代码详解

编程珠玑第一章位图排序

Java之大数据位图法(无重复排序,重复排序,去重复排序,数据压缩)

排序02-直接插入排序法

位图排序示例