Java 비트맵 정렬 사용 방법

8452 단어 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
자바 코드로 시도해 보니 과연 효율이 좋군요

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밖에 되지 않으면 효율이 매우 뚜렷하게 떨어진다...하지만 비트맵으로 정렬하는 것은 눈에 띄는 일이다.비트맵법은 일반적으로 데이터를 저장하여 어떤 데이터가 존재하지 않거나 수조의 중복 여부를 판단하는 데 쓰인다.

좋은 웹페이지 즐겨찾기