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 * @param11 */ 12 public void insertSort(T[] elements, Comparator 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) 16 * 空间复杂度:O(1) 7 * 使用场景:元素小于5000 8 * @param elements 9 * @param comparator 10 * @param11 */ 12 public void shellSort(T[] elements, Comparator 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 * @param11 */ 12 public void selectSort(T[] elements, Comparator 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 * @param10 */ 11 public void heapSort(T[] elements, Comparator comparator) { 12 if (isInputInvalid(elements, comparator)) { 13 return; 14 } 15 16 PriorityQueue 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 * @param10 */ 11 public void bubbleSort(T[] elements, Comparator 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 * @param11 */ 12 public void quickSort(T[] elements, Comparator comparator) { 13 if (isInputInvalid(elements, comparator)) { 14 return; 15 } 16 doQuickSort(elements, 0, elements.length - 1, comparator); 17 } 18 19 private void doQuickSort(T[] elements, int start, int end, Comparator 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 int partition(T[] elements, int start, int end, Comparator 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 * @param11 */ 12 public void mergeSort(T[] elements, Comparator 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 void doMergeSort(T[] elements, int start, int end, Comparator 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 void merge(T[] elements, int start, int mid, int end, Comparator 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 staticT[] dupArray(T[] array) { 38 return Arrays.copyOf(array, array.length); 39 } 40 41 private static void printArray(T[] array, String des) { 42 System.out.println(arrayToString(array) + " :" + des); 43 } 44 45 public static 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选取方法,或者在快排在递归到比较小的元素划分的时候使用插入排序等等。
文中有不足之处还请大家批评指正。