/** * 快速排序 * 分治、递归思想 * 如果要排序数组中下标从 p 到 r 之间的一组数据,我们选择 p 到 r 之间的任意一个数据作为 pivot (分区点)。 我们遍历 p 到 r 之间的数据,将小于 pivot 的放到左边,将大于 pivot 的放右边,pivot 放到中间。经过这一步骤之后,数组 p 到 r 之间的数据就被分成了三个部分,前面 p 到 q-1 之间都是小于pivot的,中间是pivot,后面的q+1到r之间是大于pivot的,根据分治、递归思想,我们可以用递归排序下标从p到q-1之间的数据和下标q+1到r之间的数据,直到区间缩小为1,就说明所有的都是有序了 * 最好和平均复杂度为 O(nlogn),最坏时间复杂度为O(n²),不稳定的原地排序算法 * * @param data */ public static void quickSort(int[] data){ quickSortInternally(data,0,data.length - 1); } private static void quickSortInternally(int[] data,int p,int r){ if(p>=r) return; int midden = getMidden(data,p,r); quickSortInternally(data,p,midden - 1); quickSortInternally(data,midden + 1,r); } private static int getMidden(int[] data,int p,int r){ int i = p; int pivot = data[r]; for (int j=p;j<r ;j++){ if(data[j]<pivot){ int temp = data[i]; data[i] = data[j]; data[j] = temp; i++; } } int temp = data[i]; data[i]= data[r]; data[r] = temp; System.out.println("i="+i); return i; } /** * 归并排序 * 分治、递归思想 * 要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分进行排序,然后将排序好的两部分合并 * 最好、最坏、平均时间复杂度都为 O(nlogn),需要空间复杂度为O(n),是稳定的非原地算法 * @param data * @param p * @param r */ public static void mergeSort(int[] data,int p,int r){ //终止条件 if(p>=r) return; //防止 p和r过大,(p+r)溢出 int q = p +(r- p)/2; //分治递归 mergeSort(data,p,q); mergeSort(data,q + 1,r); // 将A[p...q]和A[q+1...r]合并为A[p...r] merge(data,p,q,r); } private static void merge(int[] data,int p,int q,int r){ int i= p; int j = q +1; int k = 0; int[] temp = new int[r-p + 1]; while (i<=q && j<=r){ if(data[i]<=data[j]){ temp[k++] = data[i++]; }else { temp[k++] = data[j++]; } } // 判断哪个子数组中有剩余的数据 int start = i; int end = q; if(j<=r){ start = j; end = r; } // 将剩余的数据拷贝到临时数组tmp while (start <= end){ temp[k++]=data[start ++]; } //将临时变量拷贝回a[p..r] for (i=0;i<=r-p;i++){ data[p+i] = temp[i]; } } /** * 冒泡排序,只会操作相邻的两个数据。每次冒泡操作都会对相邻的两个元素进行比较,看是否满足大小关系要求,如果不满足就让他互换。一次冒泡会让至少一个元素移动到它应该在的位置,重复n次,就完成了n个数据的排序工作 * 为原地稳定算法,时间复杂度为n²,最好时间复杂度为n,平均和最坏情况为n² * @param data */ public static void bubbleSort(int[] data){ if(data ==null || data.length <= 1) return; int n = data.length; for (int i=0;i<n;i++){ //提前退出标识 boolean flag =false; for(int j=0;j<n-i-1;j++){ if(data[j]>data[j+1]){ int temp = data[j]; data[j] = data[j+1]; data[j+1] = temp; flag = true; } } if(!flag) break; } } /** * 插入排序 * 首先我们将数组中数据分为两个区间,已排序和未排序区间。初始化时已排序区间只有一个元素,就是数组的第一个元素。插入算法的核心思想是取未排序算法中的元素,在已排序算法中找到合适的插入位置将其插入 * 原地稳定算法,时间复杂度为O(n2),但它赋值次数比冒泡的少(插入赋值一次,冒泡3次),所以效率比冒泡的高 * @param data */ public static void insertSort(int[] data){ if(data == null || data.length <= 1) return; for (int i=1;i<data.length;i++){ int val = data[i]; int j = i - 1; //查找插入的位置 for(; j>=0 ;j--){ if(data[j]>val){ //数据移动 data[j+1] = data[j]; }else { break; } } //找到位置插入 data [j + 1] = val; } } public static void main(String[] args) { int[] data ={6,11,3,9,8}; quickSort(data); System.out.println("快排结果为"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; mergeSort(data,0,data.length-1); System.out.println("归并排序结果为"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; bubbleSort(data); System.out.println("冒泡排序结果为"+ Arrays.toString(data)); data =new int[]{6,11,3,9,8}; insertSort(data); System.out.println("插入排序结果为"+ Arrays.toString(data)); }
java 基本排序
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.