排序算法之归并快排
排序算法
归并排序
思想: 经过多次递归,变为一个个数字。再经多次merge就可以变为有序。merge 方法中只有一个 for 循环,直接就可以得出每次合并的时间复杂度为 O(n) ,而分解数组每次对半切割,属于对数时间 O(log n) ,合起来等于 O(log2n) ,也就是说,总的时间复杂度为 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]){ arr[k] = tempArr[right++];//将右边的首位排入,然后右边的下标指针+1。 } else { arr[k] = tempArr[left++];//将左边的首位排入,然后左边的下标指针+1。 } } }
快速排序
思想: 定义第一个为基准数,先从右边扫描,找到第一个小于他的数,再从左边扫描,直到找到一个比他大的。交换,直到两个指针相遇。3,1,2,5,4到2,1,3,5,4
public class Main{ public static void main(String[] args) { int[] a={1,3,5,2,7,9,0}; quickSort(a,0,6); for (int i =0;i<a.length;i++){ System.out.println(a[i]); } } private static void quickSort(int[] arr, int low, int high) { if (low < high) { // 找寻基准数据的正确索引 int index = getIndex(arr, low, high); // 进行迭代对index之前和之后的数组进行相同的操作使整个数组变成有序 quickSort(arr, 0, index - 1); quickSort(arr, index + 1, high); } } private static int getIndex(int[] arr, int low, int high) { // 基准数据 int tmp = arr[low]; while (low < high) { // 当队尾的元素大于等于基准数据时,向前挪动high指针 while (low < high && arr[high] >= tmp) { high--; } // 如果队尾元素小于tmp了,需要将其赋值给low arr[low] = arr[high]; // 当队首元素小于等于tmp时,向前挪动low指针 while (low < high && arr[low] <= tmp) { low++; } // 当队首元素大于tmp时,需要将其赋值给high arr[high] = arr[low]; } // 跳出循环时low和high相等,此时的low或high就是tmp的正确索引位置 // 由原理部分可以很清楚的知道low位置的值并不是tmp,所以需要将tmp赋值给arr[low] arr[low] = tmp; return low; // 返回tmp的正确位置 } }