diff --git a/src/main/java/me/ehlxr/leetcode/BubbleSort.java b/src/main/java/me/ehlxr/leetcode/BubbleSort.java new file mode 100644 index 0000000..099f299 --- /dev/null +++ b/src/main/java/me/ehlxr/leetcode/BubbleSort.java @@ -0,0 +1,50 @@ +package me.ehlxr.leetcode; + +import java.util.Arrays; + +/** + * 冒泡排序 + *

+ * 它重复访问要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。 + * 访问数列的工作是重复地进行直到没有再需要交换的数据,也就是说该数列已经排序完成 + * + * @author ehlxr + * @since 2020-10-01 16:40. + */ +public class BubbleSort { + + /** + * 冒泡排序算法的算法过程如下: + * ①. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。 + * ②. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。这步做完后,最后的元素会是最大的数。 + * ③. 针对所有的元素重复以上的步骤,除了最后一个。 + * ④. 持续每次对越来越少的元素重复上面的步骤①~③,直到没有任何一对数字需要比较。 + */ + public static void sort(int[] arr) { + //外层:需要 length-1 次循环比较 + for (int i = 0; i < arr.length - 1; i++) { + + //内层:每次循环需要两两比较的次数,每次比较后,都会将当前最大的数放到最后位置,所以每次比较次数递减一次 + for (int j = 0; j < arr.length - 1 - i; j++) { + if (arr[j] > arr[j + 1]) { + swap(arr, j, j + 1); + } + } + System.out.println("Sorting: " + Arrays.toString(arr)); + } + } + + public static void swap(int[] arr, int i, int j) { + // arr[i] = arr[i] + arr[j]; + // arr[j] = arr[i] - arr[j]; + // arr[i] = arr[i] - arr[j]; + + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + public static void main(String[] args) { + sort(new int[]{4, 9, 1, 6, 8, 2}); + } +} diff --git a/src/main/java/me/ehlxr/leetcode/InsertSort.java b/src/main/java/me/ehlxr/leetcode/InsertSort.java index 2e865b0..7795398 100644 --- a/src/main/java/me/ehlxr/leetcode/InsertSort.java +++ b/src/main/java/me/ehlxr/leetcode/InsertSort.java @@ -3,7 +3,9 @@ package me.ehlxr.leetcode; import java.util.Arrays; /** - * 直接插入排序的基本思想是: + * 插入排序 + * + * 基本思想是: * 将数组中的所有元素依次跟前面已经排好的元素相比较,如果选择的元素比已排序的元素小, * 则交换,直到全部元素都比较过为止。 * @@ -14,11 +16,11 @@ public class InsertSort { /** * ①. 从第一个元素开始,该元素可以认为已经被排序 - * ②. 取出下一个元素,在已经排序的元素序列中从后向前扫描 + * ②. 取出下一个元素(新元素),在已经排序的元素序列中从后向前扫描 * ③. 如果该元素(已排序)大于新元素,将该元素移到下一位置 * ④. 重复步骤 3,直到找到已排序的元素小于或者等于新元素的位置 * ⑤. 将新元素插入到该位置后 - * ⑥. 重复步骤②~⑤ + * ⑥. 重复步骤 ②~⑤ */ public static void sort(int[] arr) { for (int i = 1; i < arr.length; i++) { diff --git a/src/main/java/me/ehlxr/leetcode/QuickSort.java b/src/main/java/me/ehlxr/leetcode/QuickSort.java index 28983ea..8632d31 100644 --- a/src/main/java/me/ehlxr/leetcode/QuickSort.java +++ b/src/main/java/me/ehlxr/leetcode/QuickSort.java @@ -2,91 +2,40 @@ package me.ehlxr.leetcode; import java.util.Arrays; +/** + * 快速排序 + *

+ * 快速排序(Quicksort)是对冒泡排序的一种改进,借用了分治的思想, + * 它的基本思想是:通过一趟排序将要排序的数据分割成独立的两部分, + * 其中一部分的所有数据都比另外一部分的所有数据都要小, + * 然后再按此方法对这两部分数据分别进行快速排序, + * 整个排序过程可以递归进行,以此达到整个数据变成有序序列。 + * + * @author ehlxr + * @since 2020-10-01 16:40. + */ public class QuickSort { - /** - * 快速排序(左右指针法) - * - * @param arr 待排序数组 - * @param low 左边界 - * @param high 右边界 - */ - public static void sort(int[] arr, int low, int high) { - if (arr == null || arr.length <= 0) { - return; - } - if (low >= high) { - return; - } - - int left = low; - int right = high; - - int key = arr[left]; - - while (left < right) { - while (left < right && arr[right] >= key) { - right--; - } - while (left < right && arr[left] <= key) { - left++; - } - if (left < right) { - swap(arr, left, right); - } - } - swap(arr, low, left); - System.out.println("Sorting: " + Arrays.toString(arr)); - sort(arr, low, left - 1); - sort(arr, left + 1, high); - } - - public static void swap(int[] arr, int low, int high) { - int tmp = arr[low]; - arr[low] = arr[high]; - arr[high] = tmp; - } - - /** - * 快速排序(挖坑法递归) - * - * @param arr 待排序数组 - * @param low 左边界 - * @param high 右边界 - */ - public static void sort2(int[] arr, int low, int high) { - if (arr == null || arr.length <= 0) { - return; - } - if (low >= high) { - return; - } - - int left = low; - int right = high; - int temp = arr[left]; //挖坑1:保存基准的值 - - while (left < right) { - while (left < right && arr[right] >= temp) { - right--; - } - arr[left] = arr[right]; //坑2:从后向前找到比基准小的元素,插入到基准位置坑1中 - while (left < right && arr[left] <= temp) { - left++; - } - arr[right] = arr[left]; //坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中 - } - arr[left] = temp; //基准值填补到坑3中,准备分治递归快排 - System.out.println("Sorting: " + Arrays.toString(arr)); - sort2(arr, low, left - 1); - sort2(arr, left + 1, high); - } - public static void main(String[] args) { - int[] arrs = {2, 4, 7, 5}; - sort3(arrs, 0, arrs.length - 1); + int[] arr = {4, 9, 1, 6, 8, 2}; + sort(arr, 0, arr.length - 1); } - public static void sort3(int[] arr, int l, int r) { + /** + * 快速排序使用分治策略来把一个序列(list)分为两个子序列(sub-lists)。 + * 步骤为: + * ①. 从数列中挑出一个元素,称为 "基准"(pivot)。 + * ②. 重新排序数列,所有比基准值小的元素摆放在基准前面,所有比基准值大的元素摆在基准后面(相同的数可以到任一边)。 + * 在这个分区结束之后,该基准就处于数列的中间位置。这个称为分区(partition)操作。 + * ③. 递归地(recursively)把小于基准值元素的子数列和大于基准值元素的子数列排序。 + *

+ * 递归到最底部时,数列的大小是零或一,也就是已经排序好了。 + * 这个算法一定会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 + * + * @param arr 待排序数组 + * @param l 左边界 + * @param r 右边界 + */ + public static void sort(int[] arr, int l, int r) { if (l >= r) { return; } @@ -95,25 +44,106 @@ public class QuickSort { return; } - int i = l, j = r, x = l; - int k = arr[x]; + int i = l, j = r, + // 一般选择数组左边界作为基准 + k = l; + int p = arr[k]; + while (l < r) { - while (l < r && arr[r] >= k) { + // 首先循环递减右边界,直到找到小于基准的元素,相互交换 + while (l < r && arr[r] >= p) { r--; } - arr[x] = arr[r]; - x = r; + arr[k] = arr[r]; + k = r; - while (l < r && arr[l] <= k) { + // 其次循环递增左边界,直到找到大于基准的元素,相互交换 + while (l < r && arr[l] <= p) { l++; } - arr[x] = arr[l]; - x = l; + arr[k] = arr[l]; + k = l; + + // 循环以上步骤,直到 l 和 r 相遇 } - arr[x] = k; + arr[k] = p; System.out.println("Sorting: " + Arrays.toString(arr)); - sort3(arr, i, x - 1); - sort3(arr, x + 1, j); + sort(arr, i, k - 1); + sort(arr, k + 1, j); + } + + /* + * 左右指针法 + */ + // public static void sort(int[] arr, int low, int high) { + // if (arr == null || arr.length <= 0) { + // return; + // } + // if (low >= high) { + // return; + // } + // + // int left = low; + // int right = high; + // + // int key = arr[left]; + // + // while (left < right) { + // while (left < right && arr[right] >= key) { + // right--; + // } + // while (left < right && arr[left] <= key) { + // left++; + // } + // if (left < right) { + // swap(arr, left, right); + // } + // } + // swap(arr, low, left); + // System.out.println("Sorting: " + Arrays.toString(arr)); + // sort(arr, low, left - 1); + // sort(arr, left + 1, high); + // } + + /* + * 挖坑法递归 + */ + // public static void sort2(int[] arr, int low, int high) { + // if (arr == null || arr.length <= 0) { + // return; + // } + // if (low >= high) { + // return; + // } + // + // int left = low; + // int right = high; + // // 挖坑1:保存基准的值 + // int temp = arr[left]; + // + // while (left < right) { + // while (left < right && arr[right] >= temp) { + // right--; + // } + // //坑2:从后向前找到比基准小的元素,插入到基准位置坑1中 + // arr[left] = arr[right]; + // while (left < right && arr[left] <= temp) { + // left++; + // } + // //坑3:从前往后找到比基准大的元素,放到刚才挖的坑2中 + // arr[right] = arr[left]; + // } + // //基准值填补到坑3中,准备分治递归快排 + // arr[left] = temp; + // System.out.println("Sorting: " + Arrays.toString(arr)); + // sort2(arr, low, left - 1); + // sort2(arr, left + 1, high); + // } + + public static void swap(int[] arr, int low, int high) { + int tmp = arr[low]; + arr[low] = arr[high]; + arr[high] = tmp; } } \ No newline at end of file diff --git a/src/main/java/me/ehlxr/leetcode/SelectSort.java b/src/main/java/me/ehlxr/leetcode/SelectSort.java new file mode 100644 index 0000000..7eb5851 --- /dev/null +++ b/src/main/java/me/ehlxr/leetcode/SelectSort.java @@ -0,0 +1,53 @@ +package me.ehlxr.leetcode; + +import java.util.Arrays; + +/** + * 选择排序 + *

+ * 在未排序序列中找到最小(大)元素,存放到未排序序列的起始位置 + * + * @author ehlxr + * @since 2020-10-01 16:55. + */ +public class SelectSort { + + /** + * ①. 从待排序序列中,找到关键字最小的元素; + * ②. 如果最小元素不是待排序序列的第一个元素,将其和第一个元素互换; + * ③. 从余下的 N - 1 个元素中,找出关键字最小的元素,重复①、②步,直到排序结束。 + */ + public static void sort(int[] arr) { + for (int i = 0; i < arr.length - 1; i++) { + // for (int j = i + 1; j < arr.length; j++) { + // if (arr[i] > arr[j]) { + // swap(arr, i, j); + // } + // } + int min = i; + for (int j = i + 1; j < arr.length; j++) { + if (arr[min] > arr[j]) { + min = j; + } + } + if (min != i) { + swap(arr, min, i); + } + System.out.println("Sorting: " + Arrays.toString(arr)); + } + } + + public static void swap(int[] arr, int i, int j) { + // arr[i] = arr[i] + arr[j]; + // arr[j] = arr[i] - arr[j]; + // arr[i] = arr[i] - arr[j]; + + int tmp = arr[i]; + arr[i] = arr[j]; + arr[j] = tmp; + } + + public static void main(String[] args) { + sort(new int[]{4, 9, 1, 6, 8, 2}); + } +} diff --git a/src/main/java/me/ehlxr/leetcode/ShellSort.java b/src/main/java/me/ehlxr/leetcode/ShellSort.java new file mode 100644 index 0000000..9835d35 --- /dev/null +++ b/src/main/java/me/ehlxr/leetcode/ShellSort.java @@ -0,0 +1,8 @@ +package me.ehlxr.leetcode; + +/** + * @author ehlxr + * @since 2020-10-01 16:40. + */ +public class ShellSort { +}