• 7种基本排序算法的Java实现


    7种基本排序算法的Java实现

    转自我的Github

    以下为7种基本排序算法的Java实现,以及复杂度和稳定性的相关信息。

    以下为代码片段,完整的代码见Sort.java

    • 插入排序
     1    /**
     2      * 直接插入排序
     3      * 不稳定
     4      * 时间复杂度:O(n^2)
     5      * 最差时间复杂度:O(n^2)
     6      * 空间复杂度:O(1)
     7      * 使用场景:大部分元素有序
     8      * @param elements
     9      * @param comparator
    10      * @param <T>
    11      */
    12     public <T> void insertSort(T[] elements, Comparator<T> comparator) {
    13         if (isInputInvalid(elements, comparator)) {
    14             return;
    15         }
    16 
    17         int length = elements.length;
    18         for (int i = 1; i < length; i++) {
    19             T current = elements[i];
    20             int j;
    21             for (j = i; j > 0; j--) {
    22                 if (comparator.compare(elements[j - 1], current) > 0) {
    23                     elements[j] = elements[j - 1];
    24                 } else {
    25                     break;
    26                 }
    27             }
    28             elements[j] = current;
    29         }
    30     }
    • Shell排序
     1    /**
     2      * 希尔排序
     3      * 不稳定
     4      * 时间复杂度:O(nlogn)
     5      * 最差时间复杂度:O(n^s) 1<s<2
     6      * 空间复杂度:O(1)
     7      * 使用场景:元素小于5000
     8      * @param elements
     9      * @param comparator
    10      * @param <T>
    11      */
    12     public <T> void shellSort(T[] elements, Comparator<T> comparator) {
    13         if (isInputInvalid(elements, comparator)) {
    14             return;
    15         }
    16         int length = elements.length;
    17         for (int gap = length/2; gap >= 1; gap /= 2) {
    18             for (int i = gap; i < length; i++) {
    19                 T current = elements[i];
    20                 int j;
    21                 for (j = i; j >= gap; j = j - gap) {
    22                     if (comparator.compare(elements[j - gap], current) > 0) {
    23                         elements[j] = elements[j - gap];
    24                     } else {
    25                         break;
    26                     }
    27                 }
    28                 elements[j] = current;
    29             }
    30 //            printArray(elements, "gap:" + gap);
    31         }
    32     }
    • 选择排序
     1    /**
     2      * 选择排序
     3      * 稳定
     4      * 时间复杂度:O(n^2)
     5      * 最差时间复杂度:O(n^2)
     6      * 空间复杂度:O(1)
     7      * 使用场景:n较少时
     8      * @param elements
     9      * @param comparator
    10      * @param <T>
    11      */
    12     public <T> void selectSort(T[] elements, Comparator<T> comparator) {
    13         if (isInputInvalid(elements, comparator)) {
    14             return;
    15         }
    16 
    17         int length = elements.length;
    18         for (int i = 0; i < length - 1; i++) {
    19             int min = i;
    20             for (int j = i + 1; j < length; j++) {
    21                 if (comparator.compare(elements[min], elements[j]) > 0) {
    22                     min = j;
    23                 }
    24             }
    25             if (min != i) {
    26                 swap(elements, min, i);
    27             }
    28         }
    29     }
    • 堆排序

    优先级队列内部实现就是一个最小堆,这里就不自己实现heap了

     1    /**
     2      * 堆排序
     3      * 时间复杂度:O(nlogn)
     4      * 最差时间复杂度:O(nlogn)
     5      * 空间复杂度:O(n)
     6      * 使用场景:n较大时
     7      * @param elements
     8      * @param comparator
     9      * @param <T>
    10      */
    11     public <T> void heapSort(T[] elements, Comparator<T> comparator) {
    12         if (isInputInvalid(elements, comparator)) {
    13             return;
    14         }
    15 
    16         PriorityQueue<T> heap = new PriorityQueue(elements.length, comparator);
    17         for (T element : elements) {
    18             heap.add(element);
    19         }
    20         for (int i = 0; i < elements.length; i++) {
    21             elements[i] = heap.poll();
    22         }
    23     }
    • 冒泡排序
     1     /**
     2      * 冒泡排序
     3      * 稳定
     4      * 时间复杂度:O(n^2)
     5      * 空间复杂度:O(1)
     6      * 使用场景:n较小时
     7      * @param elements
     8      * @param comparator
     9      * @param <T>
    10      */
    11     public <T> void bubbleSort(T[] elements, Comparator<T> comparator) {
    12         if (isInputInvalid(elements, comparator)) {
    13             return;
    14         }
    15 
    16         int length = elements.length;
    17         for (int i = 1; i < length; i++) {
    18             for (int j = length - 1; j >= i; j--) {
    19                 if (comparator.compare(elements[j - 1], elements[j]) > 0) {
    20                     swap(elements, j - 1, j);
    21                 }
    22             }
    23         }
    24     }
    • 快排
     1    /**
     2      * 快速排序
     3      * 不稳定
     4      * 时间复杂度:O(nlogn)
     5      * 最差时间复杂度:O(n^2)
     6      * 空间复杂度:O(logn)
     7      * 使用场景:由于是递归,不适合内存有限制的情况, n较大时
     8      * @param elements
     9      * @param comparator
    10      * @param <T>
    11      */
    12     public <T> void quickSort(T[] elements, Comparator<T> comparator) {
    13         if (isInputInvalid(elements, comparator)) {
    14             return;
    15         }
    16         doQuickSort(elements, 0, elements.length - 1, comparator);
    17     }
    18 
    19     private <T> void doQuickSort(T[] elements, int start, int end, Comparator<T> comparator) {
    20         if (start >= end) {
    21             return;
    22         }
    23         int pivot = partition(elements, start, end, comparator);
    24         doQuickSort(elements, start, pivot - 1, comparator);
    25         doQuickSort(elements, pivot + 1, end, comparator);
    26     }
    27 
    28     private <T> int partition(T[] elements, int start, int end, Comparator<T> comparator) {
    29         T pivot = elements[start];
    30         int pivotIndex = start, forward = start, back = end;
    31         while (forward < back) {
    32             for (; comparator.compare(pivot, elements[forward]) >= 0 && forward < end; forward++) {}
    33             for (; comparator.compare(pivot, elements[back]) <= 0 && back > start; back--) {}
    34             if (forward < back) {
    35                 swap(elements, forward++, back--);
    36             }
    37         }
    38         swap(elements, back, pivotIndex);
    39         return back;
    40     }
    • 归并排序
     1    /**
     2      * 归并排序
     3      * 不稳定
     4      * 时间复杂度:O(nlogn)
     5      * 最差时间复杂度:O(nlogn)
     6      * 空间复杂度:O(n)
     7      * 使用场景:n较大时
     8      * @param elements
     9      * @param comparator
    10      * @param <T>
    11      */
    12     public <T> void mergeSort(T[] elements, Comparator<T> comparator) {
    13         if (isInputInvalid(elements, comparator)) {
    14             return;
    15         }
    16 
    17         Object[] aux = new Object[elements.length];
    18         int start = 0, end = elements.length - 1;
    19         doMergeSort(elements, start, end, comparator, aux);
    20     }
    21 
    22     private <T> void doMergeSort(T[] elements, int start, int end, Comparator<T> comparator, Object[] aux) {
    23         if (start >= end) {
    24             return;
    25         }
    26         int mid = (start + end) / 2;
    27         doMergeSort(elements, start, mid, comparator, aux);
    28         doMergeSort(elements, mid + 1, end, comparator, aux);
    29         merge(elements, start, mid, end, comparator, aux);
    30     }
    31 
    32     private <T> void merge(T[] elements, int start, int mid, int end, Comparator<T> comparator, Object[] aux) {
    33         int lb = start, rb = mid + 1, auxIndex = start;
    34         while (lb <= mid && rb <= end) {
    35             if (comparator.compare(elements[lb], elements[rb]) <= 0) {
    36                 aux[auxIndex++] = elements[lb++];
    37             } else {
    38                 aux[auxIndex++] = elements[rb++];
    39             }
    40         }
    41 
    42         if (lb < mid + 1) {
    43             while(lb <= mid) {
    44                 aux[auxIndex++] = elements[lb++];
    45             }
    46         } else {
    47             while(rb <= end) {
    48                 aux[auxIndex++] = elements[rb++];
    49             }
    50         }
    51 
    52         for(int i = start; i <= end; i++) {
    53             elements[i] = (T) aux[i];
    54         }
    55     }
    • 测试用方法
     1    public static void main(String[] args) {
     2         Integer[] elements = {3, 543, 54, 5, 6, 2, 67, 3, 65, 4};
     3 //        Integer[] elements = {0,0,0,0,0,0,0,0,0,0,0};
     4         printArray(elements, "OriginalArray");
     5 
     6         Sort sort = new Sort();
     7 
     8         Integer[] dupArray = dupArray(elements);
     9         sort.bubbleSort(dupArray, (o1, o2) -> o1 - o2);
    10         printArray(dupArray, "BubbleSort");
    11 
    12         dupArray = dupArray(elements);
    13         sort.insertSort(dupArray, (o1, o2) -> o1 - o2);
    14         printArray(dupArray, "InsertSort");
    15 
    16         dupArray = dupArray(elements);
    17         sort.selectSort(dupArray, (o1, o2) -> o1 - o2);
    18         printArray(dupArray, "SelectSort");
    19 
    20         dupArray = dupArray(elements);
    21         sort.heapSort(dupArray, (o1, o2) -> o1 - o2);
    22         printArray(dupArray, "HeapSort");
    23 
    24         dupArray = dupArray(elements);
    25         sort.quickSort(dupArray, (o1, o2) -> o1 - o2);
    26         printArray(dupArray, "QuickSort");
    27 
    28         dupArray = dupArray(elements);
    29         sort.shellSort(dupArray, (o1, o2) -> o1 - o2);
    30         printArray(dupArray, "ShellSort");
    31 
    32         dupArray = dupArray(elements);
    33         sort.mergeSort(dupArray, (o1, o2) -> o1 - o2);
    34         printArray(dupArray, "MergeSort");
    35     }
    36 
    37     private static <T> T[] dupArray(T[] array) {
    38         return Arrays.copyOf(array, array.length);
    39     }
    40 
    41     private static <T> void printArray(T[] array, String des) {
    42         System.out.println(arrayToString(array) + " :" + des);
    43     }
    44 
    45     public static <T> String arrayToString(T[] array) {
    46         StringBuilder resultBuilder = new StringBuilder();
    47         resultBuilder.append("{");
    48         for (T item : array) {
    49             resultBuilder.append(item).append(",");
    50         }
    51         resultBuilder.deleteCharAt(resultBuilder.length() - 1);
    52         resultBuilder.append("}");
    53         return resultBuilder.toString();
    54     }

    当然每种算法根据自身的缺陷都有可以改进的地方,可以结合不同的情况使用不同的排序算法,比如快排中使用三者取中的pivot选取方法,或者在快排在递归到比较小的元素划分的时候使用插入排序等等。
    文中有不足之处还请大家批评指正。

  • 相关阅读:
    树形dp--P2014 [CTSC1997]选课
    背包变形--P1759 通天之潜水
    区间dp--P1880 [NOI1995]石子合并
    动态规划--P2758 编辑距离
    筛法--CF449C Jzzhu and Apples
    BZOJ3998: [TJOI2015]弦论(后缀自动机,Parent树)
    BZOJ3530: [Sdoi2014]数数(Trie图,数位Dp)
    BZOJ1444: [Jsoi2009]有趣的游戏(Trie图,矩乘)
    BZOJ1195: [HNOI2006]最短母串(Trie图,搜索)
    BZOJ3238: [Ahoi2013]差异(后缀数组)
  • 原文地址:https://www.cnblogs.com/katsura/p/5641925.html
Copyright © 2020-2023  润新知