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,那么效率会下降的非常明显。。。。。但是,使用位图法进行排序,确实让人眼前一亮。位图法通常是用来存储数据,判断某个数据存不存在或者判断数组是否存在重复 。

(0)

相关推荐

  • java中常用的排序方法

    复制代码 代码如下: package com.test; import java.util.Random; /** * 排序测试类 *  * 排序算法的分类如下: 1.插入排序(直接插入排序.折半插入排序.希尔排序): 2.交换排序(冒泡泡排序.快速排序): * 3.选择排序(直接选择排序.堆排序): 4.归并排序: 5.基数排序. *  * 关于排序方法的选择: (1)若n较小(如n≤50),可采用直接插入或直接选择排序. * 当记录规模较小时,直接插入排序较好:否则因为直接选择移动的记录数少

  • 浅析java快速排序算法

    快速排序是找出一个元素(理论上可以随便找一个)作为基准(pivot),然后对数组进行分区操作,使基准左边元素的值都不大于基准值,基准右边的元素值 都不小于基准值,如此作为基准的元素调整到排序后的正确位置.递归快速排序,将其他n-1个元素也调整到排序后的正确位置.最后每个元素都是在排序后的正 确位置,排序完成.所以快速排序算法的核心算法是分区操作,即如何调整基准的位置以及调整返回基准的最终位置以便分治递归. 一趟快速排序的算法是: 1)设置两个变量i.j,排序开始的时候:i=0,j=N-1: 2)

  • Java中的2种集合排序方法介绍

    直接上代码: import java.util.ArrayList; import java.util.Collections; import java.util.Comparator; import java.util.List; /** * * <p> * ClassName CollectionsSort * </p> * <p> * Description 主要介绍两种集合的排序算法<br/> * 第一:java.util.Collections.s

  • Java中集合和数组的排序方式小结

    根据约定,在使用java编程的时候应尽可能的使用现有的类库,当然你也可以自己编写一个排序的方法,或者框架,但是有几个人能写得比JDK里的还要好呢?使用现有的类的另一个好处是代码易于阅读和维护,这篇文章主要讲的是如何使用现有的类库对数组和各种Collection容器进行排序,(文章中的一 部分例子来自<Java Developers Almanac 1.4>) 首先要知道两个类:java.util.Arrays和java.util.Collections(注意和Collection的区 别)Co

  • 浅析java 希尔排序(Shell)算法

    先取一个小于n的整数d1作为第一个增量,把文件的全部记录分成d1个组.所有距离为dl的倍数的记录放在同一个组中.先在各组内进行直接插入排序:然后,取第二个增量d2<d1重复上述的分组和排序,直至所取的增量dt=1(dt<dt-l<:-<d2<d1),即所有记录放在同一组中进行直接插入排序为止. 该方法实质上是一种分组插入方法. 原理图: 源代码 复制代码 代码如下: package com.zc.manythread; /**  *  * @author 偶my耶  *  *

  • 浅析java双向冒泡排序算法

    以整数升序排序为例来简单说明一下双向冒泡排序的过程:首先从前往后把最大数移到最后,然后反过来从后往前把最小的一个数移动到数组最前面,这一过程就是第一轮,然后重复这一过程,最终就会把整个数组从小到大排列好.双向冒泡排序要稍微优于传统的冒泡排序,因为双向排序时数组的两头都排序好了,我们只需要处理数组的中间部分即可,而单向即传统的冒泡排序只有尾部的元素是排好序的,这时每轮处理都需要从头一直处理到已经排好序元素的前面一个元素.虽然它在效率上有了点改进,但它也不能大幅度提高其排序的效率,这是由冒泡排序的基

  • java交换排序之奇偶排序实现方法

    本文实例讲述了java交换排序之奇偶排序实现方法.分享给大家供大家参考.具体如下: 奇偶排序,或奇偶换位排序,或砖排序,是一种相对简单的排序算法,最初发明用于有本地互连的并行计算.这是与冒泡排序特点类似的一种比较排序. 该算法中,通过比较数组中相邻的(奇-偶)位置数字对,如果该奇偶对是错误的顺序(第一个大于第二个),则交换.下一步重复该操作,但针对所有的(偶-奇)位置数字对.如此交替进行下去. 处理器数组的排序 在并行计算排序中,每个处理器对应处理一个值,并仅有与左右邻居的本地互连.所有处理器可

  • java交换排序之鸡尾酒排序实现方法

    本文实例讲述了java交换排序之鸡尾酒排序实现方法.分享给大家供大家参考.具体如下: 鸡尾酒排序,也就是定向冒泡排序, 鸡尾酒搅拌排序, 搅拌排序 (也可以视作选择排序的一种变形), 涟漪排序, 来回排序 or 快乐小时排序, 是冒泡排序的一种变形.此算法与冒泡排序的不同处在于排序时是以双向在序列中进行排序. 与冒泡排序不同的地方: 鸡尾酒排序等于是冒泡排序的轻微变形.不同的地方在于从低到高然后从高到低,而冒泡排序则仅从低到高去比较序列里的每个元素.他可以得到比冒泡排序稍微好一点的效能,原因是冒

  • 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 exp

  • 海量数据去重排序bitmap(位图法)在java中实现的两种方法

    在海量数据中查找出重复出现的元素或者去除重复出现的元素是面试中常考的文图.针对此类问题,可以使用位图法来解决.例如:已知某个文件内包含若干个电话号码,要求统计不同的号码的个数,甚至在O(n)时间复杂度内对这些号码进行排序. 位图法需要的空间很少(依赖于数据分布,但是我们也可以通过一些放啊发对数据进行处理,使得数据变得密集),在数据比较密集的时候效率非常高.例如:8位整数可以表示的最大十进制数值为99999999,如果每个数组对应于一个bit位,那么把所有的八进制整数存储起来只需要:99Mbit

  • Java实现ArrayList排序的方法详解

    目录 简介 法1:JDK8的stream 法2:Comparator#compare() 法3:Comparable#compareTo() 简介 说明 本文用示例介绍Java的ArrayList排序的方法. List排序方法 主要有三种方法(按推荐度排序): JDK8的stream Comparator#compare() Comparable#compareTo() 法1:JDK8的stream 见:一文详解Java中Stream流的使用 法2:Comparator#compare() 需求

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

    第一种是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

  • Java Collections.sort()实现List排序的默认方法和自定义方法

    1.java提供的默认list排序方法 主要代码: List<String> list = new ArrayList();list.add("刘媛媛"); list.add("王硕"); list.add("李明"); list.add("刘迪"); list.add("刘布"); //升序 Collections.sort(list,Collator.getInstance(java.uti

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

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

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

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

  • Java实现删除排序数组中重复元素的方法小结【三种方法比较】

    本文实例讲述了Java实现删除排序数组中重复元素的方法.分享给大家供大家参考,具体如下: 题目描述: 给定一个排序数组,在原数组中删除重复出现的数字,使得每个元素只出现一次,并且返回新的数组的长度. 不要使用额外的数组空间,必须在原地没有额外空间的条件下完成. 一:通过ArrayList解决 时间复杂度和空间复杂度都为O(n) ArrayList<Integer> list = new ArrayList<Integer>(); // 去掉数组中重复的元素 public int r

  • Java List集合排序实现方法解析

    这篇文章主要介绍了Java List集合排序实现方法解析,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下 1.使用 Collections 工具类中的 sort() 方法 参数不同: void sort(List list) 在自定义类User里面实现Comparable<User>接口,并重写抽象方法compareTo(Student o); void sort(List list, Comparator c) 第二个参数为了省事,可以直接使

  • Java中List排序的三种实现方法实例

    目录 前言 1.使用 Comparable 排序 2.使用 Comparator 排序 2.1 新建 Comparator 比较器 2.2 匿名类比较器 3.使用 Stream 流排序 总结 前言 在某些特殊的场景下,我们需要在 Java 程序中对 List 集合进行排序操作.比如从第三方接口中获取所有用户的列表,但列表默认是以用户编号从小到大进行排序的,而我们的系统需要按照用户的年龄从大到小进行排序,这个时候,我们就需要对 List 集合进行自定义排序操作了. ​List 排序的常见方法有以下

随机推荐