排序算法(归并排序)
关于排序算法,常见的大致有:冒泡排序、插入排序、选择排序、快速排序、归并排序、桶排序、计数排序等。每一种排序算法都有它们各自的优劣和适用场景。一般可以从这么几个角度来衡量排序算法:
1.最好时间复杂度、最坏时间复杂度、平均时间复杂度
2.是否是原地排序算法:原地排序算法,指空间复杂度为O(1)
3.是否是稳定排序算法:稳定排序算法,指如果待排序序列中有值相等的元素,经过排序之后,值相等元素的顺序保持不变
关于归并排序:
#综述: 1.冒泡排序、插入排序、选择排序算法的时间复杂度都是O(n^2)。只适合小规模数据的排序 2.归并排序、快速排序算法的时间复杂度是O(nlogn)。适合大规模数据的排序 3.归并排序、快速排序算法都应用了分治思想 #描述归并排序: 归并排序的核心思想,就是分而治之。比如要排序一个数组,先把数据从中间分成前后两个部分,然后对前后两部分分别排序,再将排好序的两部分进行合并。最终整个数组就排好序了。 #实现公式: 地推公式: merge_sort(p…r) = merge(merge_sort(p…q), merge_sort(q+1…r)) 终止条件: p >= r 不用再继续分解
代码实现:
package com.anan.algorithm; import java.util.Arrays; /** * 归并排序 */ public class MergeSort { public static void main(String[] args) { int[] a={4,5,6,3,2,1,8,9,12,11,8}; System.out.println("排序前:"+ Arrays.toString(a)); // 排序 mergeSort(a,0,a.length-1); System.out.println("排序后:"+Arrays.toString(a)); } // 第一步:拆分 public static void mergeSort(int[] a,int left,int right){ // 递归终止条件 if(left>=right)return ; // 计算中间位置 int mid = (left+right)/2; // 中间位置向左方向,左边继续拆分 mergeSort(a,left,mid); // 中间位置向右方向,右边继续拆分 mergeSort(a,mid+1,right); // 合并的过程 merge(a,left,mid+1,right); } // 第二步:合并 /** * 参数: * a:数组 * left:指向数组第一个元素 * mid:指向数组分割元素 * right:指向数组最后一个元素 */ public static void merge(int[] a,int left,int mid,int right){ // 左边数组大小 int[] leftA = new int[mid-left]; // 右边数组大小 int[] rightA = new int[right-mid+1]; // 左边数组填充数据 for(int i=left;i<mid;i++){ leftA[i-left]=a[i]; } // 右边数组填充数据 for(int j=mid;j<=right;j++){ rightA[j-mid]=a[j]; } // 定义两个位置指针 int L_INDEX=0,R_INDEX=0; // a数组第一个元素位置 int k=left; // 比较两个数组的值,将小的一个放入数组a中 while(L_INDEX<leftA.length && R_INDEX<rightA.length){ // 谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个 if(leftA[L_INDEX] < rightA[R_INDEX]){ a[k]=leftA[L_INDEX]; // 移动位置 L_INDEX++; k++; }else{ a[k] = rightA[R_INDEX]; // 移动位置 R_INDEX++; k++; } } // 如果左边的数组还没有比较完成。右边的数组已经比较完成。则将左边余下的数直接放入大数组a中 while(L_INDEX<leftA.length){ a[k] = leftA[L_INDEX]; // 移动位置 L_INDEX++; k++; } // 如果右边的数组还没有比较完成。左边的数组已经比较完成。则将右边余下的数直接放入大数组a中 while(R_INDEX<rightA.length){ a[k] = rightA[R_INDEX]; // 移动位置 R_INDEX++; k++; } } }
我们唯一能够控制的是自己的脾气和努力