
Java和Python对于对象的排序都是归并排序,因为是稳定的。
冒泡排序 时间复杂度为O(n^2)
public static void sort(int arr[]) {for(int i = 0; i < arr.length - 1; i++) {for(int j = 0; j < arr.length - 1 - i; j++) {int temp = 0;if(arr[j] > arr[j+1]) {temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}}// 优化,设置一个临时变量来标记该数组是否已经有序,如果有序就直接进入下一次遍历。public static void sort(int arr[]) {for(int i = 0; i < arr.length - 1; i++ ) {boolean isSort = true;for(int j = 0; j < arr.length - 1 - i; j++ ){int temp = 0;if(arr[j] > arr[j + 1]){temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;isSort = false;}}if(isSort){break;}}}
选择排序 时间复杂度为O(n^2)
public static void sort(int arr[]) {for (int i = 0; i < arr.length; i++ ) {int min = i; //最⼩小元素的下标for(int j = i + 1; j < arr.length; j++ ) {if(arr[j] < arr[min]) {min = j; //找最⼩小值下标}}//交换位置int temp = arr[i];arr[i] = arr[min];arr[min] = temp;}
插入排序 时间复杂度为O(n^2)
public static void sort(int[] arr) {int n = arr.length;for(int i = 1; i < n; ++i) {int value = arr[i];int j = 0;for(j = i -1; j >= 0; j--) {if(arr[j] > value) {arr[j+1] = arr[j];} else {break;}}arr[j+1] = value;}}
希尔排序 时间复杂度(n),按照间隔排,间隔里面按照插入排序排
public static void sort(int[] arr) {int length = arr.length;int gap = 1;while (gap < length) {gap = gap * 3 + 1;}while (gap > 0) {for (int i = gap; i < length; i++) {int tmp = arr[i];int j = i - gap;while (j >= 0 && arr[j] > tmp) {arr[j + gap] = arr[j];j -= gap;}arr[j + gap] = tmp;}gap = gap / 3;}}
归并排序 时间复杂度为 O(nlogn)
public static void sort(int[] arr) {int[] tempArr = new int[arr.length];sort(arr, tempArr, 0, arr.length - 1);}/*** 归并排序* @param arr 排序数组* @param tempArr 临时存储数组* @param startIndex 排序起始位置* @param endIndex 排序终⽌止位置*/private static void sort(int[] arr, int[] tempArr, int startIndex, int endIndex) {if (endIndex <= startIndex) {return;}int middleIndex = startIndex + (endIndex - startIndex) / 2;sort(arr, tempArr, startIndex, middleIndex);sort(arr, tempArr, middleIndex + 1, endIndex);merge(arr, tempArr, startIndex, middleIndex, endIndex);}/*** 归并* @param arr 排序数组* @param tempArr 临时存储数组* @param startIndex 归并起始位置 * @param middleIndex 归并中间位置 * @param endIndex 归并终⽌止位置*/private static void merge(int[] arr, int[] tempArr, int startIndex, int middleIndex, int endIndex) {// 复制要合并的数据for(int s = startIndex; s <= endIndex; s++) {tempArr[s] = arr[s];}// 左边⾸首位下标int left = startIndex;// 右边⾸首位下标int right = middleIndex + 1;for (int k = startIndex; k <= endIndex; k++) {if (left > middleIndex) {// 如果左边的⾸首位下标⼤大于中部下标,证明左边的数据已经排完了了。arr[k] = tempArr[right++];} else if (right > endIndex) {// 如果右边的⾸首位下标⼤大于了了数组⻓长度,证明右边的数据已经排完了了。arr[k] = tempArr [left++];} else if (tempArr[right] < tempArr[left]) {// 将右边的⾸首位排⼊入,然后右边的下标指针+1arr[k] = tempArr[right++];} else {// 将左边的⾸首位排⼊入,然后左边的下标指针+1arr[k] = tempArr[left++];}}}
快速排序 时间复杂度为O(nlogn)
private static void quickSort(int[] arr, int left, int right) {if (left < right) {int i, j, x;i = left;j = right;x = arr[i];while (i < j) {// 从右向左找到第一个小于x的数while (i < j && arr[j] > x) j--;if (i < j)arr[i++] = arr[j];// 从左向右找到第一个大于x的数while (i < j && arr[i] < x) i++;if (i < j)arr[j--] = arr[i];}arr[i] = x;quickSort(arr, left,i - 1);quickSort(arr,i + 1, right);}}
桶排序,不常用,复杂,
主要应用为计数排序和基数排序
计数排序,求众数
非比较思想、量大数小
private static int getMax(int[] a) {int max;max = a[0];for (int i = 1; i < a.length; i++)if (a[i] > max)max = a[i];return max;}public static int[] sort(int[] a, int max) {int[] count = new int[++max];int[] result = new int[a.length];if (a == null || max < 1)return null;// 1. 计数for(int i = 0; i < a.length; i++)count[a[i]]++;// 2. 排序,稳定for (int i = 1; i < count.length; i++) {count[i] = count[i] + count[i-1];}for (int i = a.length - 1; i >= 0; i--) {result[--count[a[i]]] = a[i];}return result;}
基数排序
非比较思想、桶思想的一种、多关键字排序
堆排序,最大堆通常被用来进行”升序”排序,而最小堆通常被用来进行”降序”排序
public static void maxHeapDown(int[] a, int start, int end) {int c = start; // 当前(current)节点的位置int l = 2 * c + 1; // 左(left)孩子的位置int tmp = a[c]; // 当前(current)节点的大小for (; l <= end; c = l,l = 2 * l + 1) {// "l"是左孩子,"l+1"是右孩子if (l < end && a[l] < a[l+1])l++; // 左右两孩子中选择较大者,即m_heap[l+1]if (tmp >= a[l])break; // 调整结束else { // 交换值a[c] = a[l];a[l]= tmp;}}}public static void heapSortAsc(int[] a, int n) {int i,tmp;// 从(n/2-1) --> 0逐次遍历。遍历之后,得到的数组实际上是一个(最大)二叉堆。for (i = n / 2 - 1; i >= 0; I--)maxHeapDown(a, i, n-1);// 从最后一个元素开始对序列进行调整,不断的缩小调整的范围直到第一个元素for (i = n - 1; i > 0; I--) {// 交换a[0]和a[i]。交换后,a[i]是a[0...i]中最大的。tmp = a[0];a[0] = a[i];a[i] = tmp;// 调整a[0...i-1],使得a[0...i-1]仍然是一个最大堆。// 即,保证a[i-1]是a[0...i-1]中的最大值。maxHeapDown(a, 0, i-1);}}
