排序算法学习
顶部膜拜大神:https://www.cnblogs.com/onepixel/articles/7674659.html,https://blog.csdn.net/qq_38963493/article/details/80204118
突然发现得先理解,再记住,能够达到提到算法的名字,就能手敲,写出来的地步;
排序算法的使用场景
冒泡排序 * 时间复杂度O(n^2),空间复杂度O(1),稳定 * 适用场合:数据量量不大,对稳定性有要求,且数据基本有序的情况下
插入排序* 时间复杂度O(n^2),空间复杂度O(1),稳定 * 适用场合:数据量不大,对算法的稳定性有要求,且数据局部或者整体有序的情况,小规模如10个数平均时间最快,可以在快排中调用
选择排序 * 时间复杂度O(n^2),空间复杂度O(1),不稳定 * 适用场合:当数据量不大,且对稳定性没有要求的时候
快速排序
* 时间复杂度O(n log n),空间复杂度O(n log n),不稳定,选好枢纽元是使坏情况发生的关键
* 截断范围选10比较合适,进入截断范围改用小规模高效率算法对小片段排序
* 适用场合:数值范围较大,相同值的概率较小,数据量大且不考虑稳定性的情况,数值远大于数据量时威力更大
希尔排序
* 使用简单的希尔增量序列,复杂的增量序列中Sedgewick 增量序列最坏时间复杂度达到O(n^1.3)
* 时间复杂度取决于增量序列,空间复杂度O(1),不稳定!!!
* 适用场合:数据量较大,不要求稳定性
1.冒泡排序
自己理解:数组中循环比较前一个元素和后一个元素的大小,如果前一个大于后一个元素就进行交换,比较到最后,数组中的最后一个值就是最大的那个了,然后继续比较剩下的元素,直到比较完成
//冒泡排序 public static void maoSort(int[] arr) { int len = arr.length; for (int i = 0; i < len - 1; i++) { for (int j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j + 1]) { int temp = arr[j]; arr[j] = arr[j + 1]; arr[j + 1] = temp; } } } }
2.选择排序
个人理解:先以数组第一个值为基准值,比较数组其他元素,找到最小的元素,并与当前基准值交换,然后以数组第二个元素为基准值,比较数组其他元素,找到最小的元素,并与当前基准值交换,以此类推。排序完成
//选择排序 public static void selectSort(int[] arr) { int min,temp; for (int i = 0; i < arr.length-1; i++) { min = i; for (int j = i+1; j < arr.length; j++) { if (arr[j]<arr[min]){ min=j; } } temp = arr[i]; arr[i]=arr[min]; arr[min]=temp; } }
3.插入排序
个人理解:
第一轮:把数组第一个元素当作已排序队列,拿第二个元素比较第一个元素,大于就把该元素插入到第一个元素后面
第二轮:前两个元素作为已排序队列,拿第三个元素从后往前比已排序队列,大于第i-1个元素并小第i个元素,把元素插入到i位置
以此类推
当元素小于已排序列表的第一个元素时,pre为-1,插入到已排序数组首位
public static void insertSort(int[] a){ int len = a.length; int pre,current; for (int i = 1; i <len ; i++) { pre = i-1; current = a[i]; while (pre>=0&&a[pre]>current){ a[pre+1] = a[pre]; pre--; } a[pre+1] = current; } }
4.希尔排序
基于插入排序的排序算法
public static void shellSort(int[] arr){ int length = arr.length; int temp; for (int step = length / 2; step >= 1; step /= 2) { for (int i = step; i < length; i++) { temp = arr[i]; int j = i - step; while (j >= 0 && arr[j] > temp) { arr[j + step] = arr[j]; j -= step; } arr[j + step] = temp; } } }
5.归并排序
public static void guiSort(int[] arr,int[] result, int start, int end){ if (start >= end) return; int len = end - start, mid = (len >> 1) + start; int start1 = start, end1 = mid; int start2 = mid + 1, end2 = end; guiSort(arr, result, start1, end1); guiSort(arr, result, start2, end2); int k = start; while (start1 <= end1 && start2 <= end2) result[k++] = arr[start1] < arr[start2] ? arr[start1++] : arr[start2++]; while (start1 <= end1) result[k++] = arr[start1++]; while (start2 <= end2) result[k++] = arr[start2++]; for (k = start; k <= end; k++) arr[k] = result[k]; }
6.快速排序
public static int[] quickSort(int arr[],int start,int end) { int pivot = arr[start]; int i = start; int j = end; while (i<j) { while ((i<j)&&(arr[j]>pivot)) { j--; } while ((i<j)&&(arr[i]<pivot)) { i++; } if ((arr[i]==arr[j])&&(i<j)) { i++; } else { int temp = arr[i]; arr[i] = arr[j]; arr[j] = temp; } } if (i-1>start) arr=quickSort(arr,start,i-1); if (j+1<end) arr=quickSort(arr,j+1,end); return (arr); }
7.堆排序
public static int[] heapSort(int[] array) { //这里元素的索引是从0开始的,所以最后一个非叶子结点array.length/2 - 1 for (int i = array.length / 2 - 1; i >= 0; i--) { adjustHeap(array, i, array.length); //调整堆 } // 上述逻辑,建堆结束 // 下面,开始排序逻辑 for (int j = array.length - 1; j > 0; j--) { // 元素交换,作用是去掉大顶堆 // 把大顶堆的根元素,放到数组的最后;换句话说,就是每一次的堆调整之后,都会有一个元素到达自己的最终位置 swap(array, 0, j); // 元素交换之后,毫无疑问,最后一个元素无需再考虑排序问题了。 // 接下来我们需要排序的,就是已经去掉了部分元素的堆了,这也是为什么此方法放在循环里的原因 // 而这里,实质上是自上而下,自左向右进行调整的 adjustHeap(array, 0, j); } return array; } /** * 整个堆排序最关键的地方 * @param array 待组堆 * @param i 起始结点 * @param length 堆的长度 */ public static void adjustHeap(int[] array, int i, int length) { // 先把当前元素取出来,因为当前元素可能要一直移动 int temp = array[i]; for (int k = 2 * i + 1; k < length; k = 2 * k + 1) { //2*i+1为左子树i的左子树(因为i是从0开始的),2*k+1为k的左子树 // 让k先指向子节点中最大的节点 if (k + 1 < length && array[k] < array[k + 1]) { //如果有右子树,并且右子树大于左子树 k++; } //如果发现结点(左右子结点)大于根结点,则进行值的交换 if (array[k] > temp) { swap(array, i, k); // 如果子节点更换了,那么,以子节点为根的子树会受到影响,所以,循环对子节点所在的树继续进行判断 i = k; } else { //不用交换,直接终止循环 break; } } } /** * 交换元素 * @param arr * @param a 元素的下标 * @param b 元素的下标 */ public static void swap(int[] arr, int a, int b) { int temp = arr[a]; arr[a] = arr[b]; arr[b] = temp; }
根据大神的动图,我能明白意思,但还是记不住...实现不了

浙公网安备 33010602011771号