diff --git a/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/MergeSort.java b/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/MergeSort.java new file mode 100644 index 0000000..36674dd --- /dev/null +++ b/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/MergeSort.java @@ -0,0 +1,213 @@ +package com.jackie.algo.geek.time.chapter12_sort; + +/** + * @Author: Jackie + * @date 2019/1/20 + * + * https://www.cnblogs.com/of-fanruice/p/7678801.html + * https://www.cnblogs.com/Java3y/p/8631584.html + * 归并排序是稳定的排序 + * 时间复杂度为O(nlgn) + */ +public class MergeSort { + + + public static void main(String[] args) { + int[] arr = new int[]{5,3,6,7,8,31,56,32,2}; + mergeSort(arr, 0,8); + for (int i = 0; i < arr.length; i++) { + System.out.print(arr[i] + " "); + } + } + + /** + * 归并排序 + * + * @param arrays + * @param L 指向数组第一个元素 + * @param R 指向数组最后一个元素 + */ + public static void mergeSort(int[] arrays, int L, int R) { + + //如果只有一个元素,那就不用排序了 + if (L == R) { + return; + } else { + + //取中间的数,进行拆分 + int M = (L + R) / 2; + + //左边的数不断进行拆分 + mergeSort(arrays, L, M); + + //右边的数不断进行拆分 + mergeSort(arrays, M + 1, R); + + //合并 + merge(arrays, L, M + 1, R); + + } + } + + + /** + * 合并数组 + * + * @param arrays + * @param L 指向数组第一个元素 + * @param M 指向数组分隔的元素 + * @param R 指向数组最后的元素 + */ + public static void merge(int[] arrays, int L, int M, int R) { + + //左边的数组的大小 + int[] leftArray = new int[M - L]; + + //右边的数组大小 + int[] rightArray = new int[R - M + 1]; + + //往这两个数组填充数据 + for (int i = L; i < M; i++) { + leftArray[i - L] = arrays[i]; + } + for (int i = M; i <= R; i++) { + rightArray[i - M] = arrays[i]; + } + + + int i = 0, j = 0; + // arrays数组的第一个元素 + int k = L; + + + //比较这两个数组的值,哪个小,就往数组上放 + while (i < leftArray.length && j < rightArray.length) { + + //谁比较小,谁将元素放入大数组中,移动指针,继续比较下一个 + if (leftArray[i] < rightArray[j]) { + arrays[k++] = leftArray[i++]; + } else { + arrays[k++] = rightArray[j++]; + } + } + + //如果左边的数组还没比较完,右边的数都已经完了,那么将左边的数抄到大数组中(剩下的都是大数字) + /** 至于为什么可以直接把数组没有遍历的数据直接抄到大数组中,是因为在前面的拆分的时候已经拆到最小粒度了 + * 即已经到单个元素了,然后在进行每一个合并的时候,都是保证了各个小集合中是有序的,举例,假设经过上面的处理 + * 原来两个子集合的数据如下arr1:[1,5,6] arr2:[2,3,4] + * 那这时候显然左边的数组在排序后还剩下[5,6]是需要并入到大数组中的 + * 显然arr1和arr2本身都是有序的其次,如果arr2都遍历完了,那说明arr1中剩余的元素都是比arr2中的元素大 + * 而且arr1是有序,所以可以直接抄到大数组 + * + * 下面的rightArray也是同样的道理 + */ + while (i < leftArray.length) { + arrays[k++] = leftArray[i++]; + } + //如果右边的数组还没比较完,左边的数都已经完了,那么将右边的数抄到大数组中(剩下的都是大数字) + while (j < rightArray.length) { + arrays[k++] = rightArray[j++]; + } + } + + + //========================这种方案简洁易懂========================================== + + +// +// +// public static int[] sort(int[] a,int low,int high){ +// int mid = (low+high)/2; +// if(low= r) return; +// +// // 取p到r之间的中间位置q,防止(p+r)的和超过int类型最大值 +// int q = p + (r - p) / 2; +// // 分治递归 +// mergeSortInternally(a, p, q); +// mergeSortInternally(a, q + 1, r); +// +// // 将A[p...q]和A[q+1...r]合并为A[p...r] +// merge(a, p, q, r); +// } +// +// private static void merge(int[] a, int p, int q, int r) { +// int i = p; +// int j = q + 1; +// int k = 0; // 初始化变量i, j, k +// int[] tmp = new int[r - p + 1]; // 申请一个大小跟a[p...r]一样的临时数组 +// while (i <= q && j <= r) { +// if (a[i] <= a[j]) { +// tmp[k++] = a[i++]; // i++等于i:=i+1 +// } else { +// tmp[k++] = a[j++]; +// } +// } +// +// // 判断哪个子数组中有剩余的数据 +// int start = i; +// int end = q; +// if (j <= r) { +// start = j; +// end = r; +// } +// +// // 将剩余的数据拷贝到临时数组tmp +// while (start <= end) { +// tmp[k++] = a[start++]; +// } +// +// // 将tmp中的数组拷贝回a[p...r] +// for (i = 0; i <= r - p; ++i) { +// a[p + i] = tmp[i]; +// } +// } + +} \ No newline at end of file diff --git a/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/QuickSort.java b/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/QuickSort.java new file mode 100644 index 0000000..49c3273 --- /dev/null +++ b/algo/geek-time-algo/src/main/java/com/jackie/algo/geek/time/chapter12_sort/QuickSort.java @@ -0,0 +1,53 @@ +package com.jackie.algo.geek.time.chapter12_sort; + +/** + * @Author: Jackie + * @date 2019/1/20 + */ +public class QuickSort { + + public static void main(String[] args) { + int[] arr = new int[]{3,2,6,1,4}; + quickSort(arr, arr.length); + for (int i = 0; i= r) return; + + int q = partition(a, p, r); // 获取分区点 + quickSortInternally(a, p, q-1); + quickSortInternally(a, q+1, r); + } + + private static int partition(int[] a, int p, int r) { + int pivot = a[r]; + int i = p; + for(int j = p; j < r; ++j) { + if (a[j] < pivot) { + if (i == j) { + ++i; + } else { + int tmp = a[i]; + a[i++] = a[j]; + a[j] = tmp; + } + } + } + + int tmp = a[i]; + a[i] = a[r]; + a[r] = tmp; + + System.out.println("i=" + i); + return i; + } +}