Java 位图法排序的使用方法_java

java JDK里面容器类的排序算法使用的主要是插入排序和归并排序,可能不同版本的实现有所不同,关键代码如下:

复制代码 代码如下:

/**
     * Performs a sort on the section of the array between the given indices
     * using a mergesort with exponential search algorithm (in which the merge
     * is performed by exponential search). n*log(n) performance is guaranteed
     * and in the average case it will be faster then any mergesort in which the
     * merge is performed by linear search.
     *
     * @param in -
     *            the array for sorting.
     * @param out -
     *            the result, sorted array.
     * @param start
     *            the start index
     * @param end
     *            the end index + 1
     */
    @SuppressWarnings("unchecked")
    private static void mergeSort(Object[] in, Object[] out, int start,
            int end) {
        int len = end - start;
        // use insertion sort for small arrays
        if (len <= SIMPLE_LENGTH) {
            for (int i = start + 1; i < end; i++) {
                Comparable<Object> current = (Comparable<Object>) out[i];
                Object prev = out[i - 1];
                if (current.compareTo(prev) < 0) {
                    int j = i;
                    do {
                        out[j--] = prev;
                    } while (j > start
                            && current.compareTo(prev = out[j - 1]) < 0);
                    out[j] = current;
                }
            }
            return;
        }
        int med = (end + start) >>> 1;
        mergeSort(out, in, start, med);
        mergeSort(out, in, med, end);

        // merging

        // if arrays are already sorted - no merge
        if (((Comparable<Object>) in[med - 1]).compareTo(in[med]) <= 0) {
            System.arraycopy(in, start, out, start, len);
            return;
        }
        int r = med, i = start;

        // use merging with exponential search
        do {
            Comparable<Object> fromVal = (Comparable<Object>) in[start];
            Comparable<Object> rVal = (Comparable<Object>) in[r];
            if (fromVal.compareTo(rVal) <= 0) {
                int l_1 = find(in, rVal, -1, start + 1, med - 1);
                int toCopy = l_1 - start + 1;
                System.arraycopy(in, start, out, i, toCopy);
                i += toCopy;
                out[i++] = rVal;
                r++;
                start = l_1 + 1;
            } else {
                int r_1 = find(in, fromVal, 0, r + 1, end - 1);
                int toCopy = r_1 - r + 1;
                System.arraycopy(in, r, out, i, toCopy);
                i += toCopy;
                out[i++] = fromVal;
                start++;
                r = r_1 + 1;
            }
        } while ((end - r) > 0 && (med - start) > 0);

        // copy rest of array
        if ((end - r) <= 0) {
            System.arraycopy(in, start, out, i, med - start);
        } else {
            System.arraycopy(in, r, out, i, end - r);
        }
    }

看到编程珠玑上有一个很有趣的排序算法-位图法其思想是用1位来表示[0~n-1]中的整数是否存在。1表示存在,0表示不存在。即将正整数映射到bit集合中,每一个bit代表其映射的正整数是否存在。

比如{1,2,3,5,8,13}使用下列集合表示:

  0 1 1 1 0 1 0 0 1 0 0 0 0 1 0 0 0 0 0 0

伪代码如下:

for (i  in  [0~n-1])  bit[i] = 0;
for(i  in [0~n-1])
  if (i in input file)     
    bit[i] = 1

for(i  in [0~n-1])
  if(bit[i] == 1) 
    output i

用java 代码尝试下,效率果然不错:

复制代码 代码如下:

public class javaUniqueSort {
    public static int[] temp = new int[1000001];
    public static List<Integer> tempList = new ArrayList<Integer>();
    public static int count;

    public static void main(final String[] args) {
        List<Integer> firstNum = new ArrayList<Integer>();
        List<Integer> secondNum = new ArrayList<Integer>();

        for (int i = 1; i <= 1000000; i++) {
            firstNum.add(i);
            secondNum.add(i);
        }

        Collections.shuffle(firstNum);
        Collections.shuffle(secondNum);

        getStartTime();
        Collections.sort(firstNum);
        getEndTime("java sort run time  ");

        getStartTime();
        secondNum = uniqueSort(secondNum);
        getEndTime("uniqueSort run time ");

    }

    public static List<Integer> uniqueSort(final List<Integer> uniqueList) {
        javaUniqueSort.tempList.clear();
        for (int i = 0; i < javaUniqueSort.temp.length; i++) {
            javaUniqueSort.temp[i] = 0;
        }
        for (int i = 0; i < uniqueList.size(); i++) {
            javaUniqueSort.temp[uniqueList.get(i)] = 1;
        }
        for (int i = 0; i < javaUniqueSort.temp.length; i++) {
            if (javaUniqueSort.temp[i] == 1) {
                javaUniqueSort.tempList.add(i);
            }
        }

        return javaUniqueSort.tempList;
    }

    public static void getStartTime() {
        javaShuffle.start = System.nanoTime();
    }

    public static void getEndTime(final String s) {
        javaShuffle.end = System.nanoTime();
        System.out.println(s + ": " + (javaShuffle.end - javaShuffle.start) + "ns");
    }
}

运行时间:

java sort run time  : 1257737334ns
uniqueSort run time : 170228290ns
java sort run time  : 1202749828ns
uniqueSort run time : 169327770ns

如果有重复数据,可以修改下:

复制代码 代码如下:

public class javaDuplicateSort {
    public static List<Integer> tempList = new ArrayList<Integer>();
    public static int count;

    public static void main(final String[] args) {
        Random random = new Random();
        List<Integer> firstNum = new ArrayList<Integer>();
        List<Integer> secondNum = new ArrayList<Integer>();

        for (int i = 1; i <= 100000; i++) {
            firstNum.add(i);
            secondNum.add(i);
            firstNum.add(random.nextInt(i + 1));
            secondNum.add(random.nextInt(i + 1));
        }
        Collections.shuffle(firstNum);
        Collections.shuffle(secondNum);

        getStartTime();
        Collections.sort(firstNum);
        getEndTime("java sort run time  ");

        getStartTime();
        secondNum = uniqueSort(secondNum);
        getEndTime("uniqueSort run time ");

    }

    public static List<Integer> uniqueSort(final List<Integer> uniqueList) {
        javaDuplicateSort.tempList.clear();
        int[] temp = new int[200002];
        for (int i = 0; i < temp.length; i++) {
            temp[i] = 0;
        }
        for (int i = 0; i < uniqueList.size(); i++) {
            temp[uniqueList.get(i)]++;
        }
        for (int i = 0; i < temp.length; i++) {
            for (int j = temp[i]; j > 0; j--) {
                javaDuplicateSort.tempList.add(i);
            }
        }

        return javaDuplicateSort.tempList;
    }

    public static void getStartTime() {
        javaShuffle.start = System.nanoTime();
    }

    public static void getEndTime(final String s) {
        javaShuffle.end = System.nanoTime();
        System.out.println(s + ": " + (javaShuffle.end - javaShuffle.start) + "ns");
    }
}

这种算法还是有很明显的局限性的,比如说要知道数据中最大的数值,更重要的是数据的疏密程度,比如说最大值为1000000而要数组大小只有100,那么效率会下降的非常明显。。。。。但是,使用位图法进行排序,确实让人眼前一亮。位图法通常是用来存储数据,判断某个数据存不存在或者判断数组是否存在重复 。

时间: 2024-09-20 00:13:23

Java 位图法排序的使用方法_java的相关文章

Java Map 按key排序和按Value排序的实现方法_java

一.理论准备 Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法. HashMap的值是没有顺序的,它是按照key的HashCode来实现的,对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeM

Java Map 按照Value排序的实现方法_java

Map是键值对的集合接口,它的实现类主要包括:HashMap,TreeMap,Hashtable以及LinkedHashMap等. •TreeMap:基于红黑树(Red-Black tree)的 NavigableMap 实现,该映射根据其键的自然顺序进行排序,或者根据创建映射时提供的 Comparator 进行排序,具体取决于使用的构造方法. •HashMap的值是没有顺序的,它是按照key的HashCode来实现的,对于这个无序的HashMap我们要怎么来实现排序呢?参照TreeMap的va

用Java集合中的Collections.sort方法如何对list排序(两种方法)_java

第一种是list中的对象实现Comparable接口,如下: /** * 根据order对User排序 */ public class User implements Comparable <user> { private String name; private Integer order; public String getName() { return name; } public void setName(String name) { this.name = name; } publi

编程珠玑--位图法排序

题目:一个最多包含n个正整数的文件,每个数都小于n,其中n=10^7,且所有正整数都不重复.求如何将这n个正整数升序排列. 约束:最多有1MB的内存空间可用,有充足的磁盘存储空间.   分析:这个题目的最大亮点是只有1MB的内存空间,我们可以通过计算得出,内存只有1MB可以储存的int(4byte)有10^3*10^3/4=250 000个号码.而包含正整数的文件约为10^7个int大小.这意味着无法将所有文件中的正整数一次读取进入到内存空间中去进行排序算法.因此衍生出下面两种方法:   方法1

JAVA随机打乱数组顺序的方法_java

本文实例讲述了JAVA随机打乱数组顺序的方法.分享给大家供大家参考.具体实现方法如下: 复制代码 代码如下: import java.util.Random;        public class RandomSort {        private Random random = new Random();        //数组大小        private static final int SIZE = 10;        //要重排序的数组        private int

Java获取随机数的3种方法_java

主要介绍了Java获取随机数的3种方法,主要利用random()函数来实现 方法1 (数据类型)(最小值+Math.random()*(最大值-最小值+1))例: (int)(1+Math.random()*(10-1+1)) 从1到10的int型随数 方法2 获得随机数 for (int i=0;i<30;i++) {System.out.println((int)(1+Math.random()*10));} (int)(1+Math.random()*10) 通过java.Math包的ra

java递归法求字符串逆序_java

本文实例讲述了java递归法求字符串逆序的方法.分享给大家供大家参考.具体实现方法如下: public static String reverseString(String x) { if(x==null || x.length()<2) return x; return reverseString(x.substring(1,x.length()))+ x.charAt(0); } 希望本文所述对大家的java程序设计有所帮助. 以上是小编为您精心准备的的内容,在的博客.问答.公众号.人物.课

在Java下利用log4j记录日志的方法_java

1.前言 log4j是一个用Java编写的可靠,快速和灵活的日志框架(API),它在Apache软件许可下发布. Log4j已经被移植到了C,C++,C#,Perl,Python和Ruby等语言中. Log4j是高度可配置的,并可通过在运行时的外部文件配置.它根据记录的优先级别,并提供机制,以指示记录信息到许多的目的地,例如:数据库,文件,控制台,UNIX系统日志等. Log4j中有三个主要组成部分:     loggers: 负责捕获记录信息.     appenders : 负责发布日志信息

Java实现洗牌发牌的方法_java

本文实例讲述了Java实现洗牌发牌的方法.分享给大家供大家参考.具体如下: import java.util.*; public class Main { /** * @param args the command line arguments */ static int numbersOfPlayers = 4; static int numbersOfHandCard = 13; public static void main(String[] args) { // TODO code ap