diff --git a/3.排序算法/src/sort/exchange/HeapSort.java b/3.排序算法/src/sort/exchange/HeapSort.java new file mode 100644 index 0000000..4aaec6b --- /dev/null +++ b/3.排序算法/src/sort/exchange/HeapSort.java @@ -0,0 +1,71 @@ +package sort.exchange; + +import util.ArrayUtil; + +import java.util.Arrays; + +/** + * 类功能简述:堆排序,不懂堆的建议看这个堆讲解 + * 类功能详述: 基于升序排序.过程如下: + *

+ * 1. 构建大顶堆(升序用大顶堆,降序用小顶堆) ,i=arr.lengh-1,n=arr.lengh + * 2. 将arr[0]和arr[i]互换, + * 3. i-- + * 4. 重新将arr 0到i 构建为大顶堆 + * 5. 重复2,3,4直到i=1 + *

+ * 构建大顶堆过程如下: + * 从最后一个非叶子节点开始从下往上进行调整。 + * 将该节点的值调整为max(节点值,直接子节点值),注意如果产生了交换操作还要调整被交换节点,让其也是max(节点值,直接子节点值),直到被交换节点无子节点 + * + * @author fanxb + * @date 2019/7/31 19:02 + */ +public class HeapSort { + + + private static void sort(Integer[] arr) { + int n = arr.length; + //构建大顶堆 + for (int i = n / 2 - 1; i >= 0; i--) { + adjustHeap(arr, i, n); + } + //排序 + for (int i = n - 1; i > 0; i--) { + ArrayUtil.swap(arr, 0, arr[i]); + adjustHeap(arr, 0, i); + } + } + + /** + * Description: 调整堆 + * + * @param arr 数组 + * @param index 调整index处的对结构 + * @param length 堆大小 + * @author fanxb + * @date 2019/7/31 19:50 + */ + private static void adjustHeap(Integer[] arr, int index, int length) { + if (index >= length) { + return; + } + int maxIndex = index; + for (int i = 2 * index + 1; i < length - 1 && i <= 2 * index + 2; i++) { + if (arr[maxIndex] < arr[i]) { + maxIndex = i; + } + } + //如果进行了交换,还要调整被交换节点 + if (maxIndex != index) { + ArrayUtil.swap(arr, maxIndex, index); + adjustHeap(arr, maxIndex, length); + } + } + + public static void main(String[] args) { + Integer[] arr = {1, 65, 32, 334, 12, 21, 65, 112, 444443}; + ShellSort.sort(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git a/3.排序算法/src/sort/exchange/InsertSort.java b/3.排序算法/src/sort/exchange/InsertSort.java new file mode 100644 index 0000000..356532f --- /dev/null +++ b/3.排序算法/src/sort/exchange/InsertSort.java @@ -0,0 +1,37 @@ +package sort.exchange; + +import java.util.Arrays; + +/** + * 类功能简述:插入排序 + * 类功能详述:按照升序讲解 + * 将数组分为有序部分和无序部分,最开始的有序部分为空,无序部分为整个数组 + * 1. 取无序部分第一个值temp + * 2. 和有序部分从后向前比较,如果有序部分的值大于temp,则该值向后移动一位,继续比较;如果有序部分值小于等于temp, + * 将temp放到这个值后一位(前面的移动就是为了给temp留位子),a成功插入到有序部分中。 + * 3. 重复1和2 + * + * @author fanxb + * @date 2019/7/31 16:46 + */ +public class InsertSort { + + public static void sort(Integer[] arr) { + for (int i = 0, length = arr.length; i < length; i++) { + //有序部分从后向前比较 + int j = i, temp = arr[i]; + //如果arr[j-1]<=temp,说明arr[j]需为temp,否则将arr[j-1]向后移动一位 + for (; j > 0 && temp < arr[j - 1]; j--) { + arr[j] = arr[j - 1]; + } + arr[j] = temp; + System.out.println("当前数组状态为:"+Arrays.toString(arr)); + } + } + + public static void main(String[] args) { + Integer[] arr = {1, 65, 32, 12, 21}; + InsertSort.sort(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git a/3.排序算法/src/sort/exchange/MergeSort.java b/3.排序算法/src/sort/exchange/MergeSort.java new file mode 100644 index 0000000..07cad2d --- /dev/null +++ b/3.排序算法/src/sort/exchange/MergeSort.java @@ -0,0 +1,68 @@ +package sort.exchange; + +import java.util.ArrayList; + +/** + * 类功能简述:归并排序 + * 类功能详述: + *

+ * 定义:参见维基百科 + * + * @author fanxb + * @date 2019/8/5 16:25 + */ +public class MergeSort { + + public static void mergeSort(Integer[] arr, int start, int end) { + if (start >= end) { + return; + } + int half = (start + end) / 2; + mergeSort(arr, start, half); + mergeSort(arr, half + 1, end); + merge(arr, start, half, end); + } + + /** + * Description: + * + * @param arr arr + * @author fanxb + * @date 2019/8/5 17:36 + */ + public static void merge(Integer[] arr, int start, int half, int end) { + ArrayList tempList = new ArrayList<>(); + int i = start, j = half + 1; + // 循环比较,将较小的放到tempList中 + while (i <= half && j <= end) { + if (arr[i] <= arr[j]) { + tempList.add(arr[i]); + i++; + } else { + tempList.add(arr[j]); + j++; + } + } + if (i > half) { + //说明第一个数组已经完了,将第二个数组的剩余部分放到tempList中 + while (j <= end) { + tempList.add(arr[j]); + j++; + } + } else { + //说明第二个数组卖完了,将第二个数组剩余部分放到tempList中 + while (j <= half) { + //说明第二个数组处理完了 + tempList.add(arr[j]); + j++; + } + } + + + } + + public static void main(String[] args) { + Integer[] arr = {4, 3, 1, 2, 5, 4, 2, 54}; + mergeSort(arr, 0, arr.length); + } +} diff --git a/3.排序算法/src/sort/exchange/QuickSort.java b/3.排序算法/src/sort/exchange/QuickSort.java index fb17526..bce5584 100644 --- a/3.排序算法/src/sort/exchange/QuickSort.java +++ b/3.排序算法/src/sort/exchange/QuickSort.java @@ -1,13 +1,14 @@ package sort.exchange; import util.ArrayUtil; -import util.NumberUtil; import java.util.Arrays; /** * 类功能简述:快速排序 - * 类功能详述:使用了分治的思想,先取一个数,然后让这个数的左边都是小于等于它的,右边都大于等于它,然后左边右边分布做同样的处理, + * 类功能详述: + * 1.使用了分治的思想,先取一个数作为基数(一般选第一个数),然后将这个数移动到一个合适的位置使左边的都比它小,右边的都比他大 + * 2.递归处理这个数左边的数和右边的数,直到所有的数都有序。 * 直到所有的数都有序 * * @author fanxb @@ -19,33 +20,33 @@ public class QuickSort { if (start >= end) { return; } - int baseIndex = NumberUtil.getRandom(start, end); - int base = arr[baseIndex], i = start, j = end; + int base = arr[start], i = start, j = end; while (i < j) { + //在右边找一个比基数小的数,直到i,j相等 while (arr[j] >= base && j > i) { j--; } - while (arr[i] <= base && i < j) { + + //在左边找一个比基数大的数,直到i,j相等 + while (arr[i] <= base && j > i) { i++; } - - + //如果ij不相等,交换其值 if (i < j) { ArrayUtil.swap(arr, i++, j--); - System.out.println(Arrays.toString(arr)); } } - boolean isSwap = (baseIndex > j && arr[baseIndex] < arr[j]) || (baseIndex < j && arr[baseIndex] > arr[j]); - if (isSwap) { - ArrayUtil.swap(arr, baseIndex, i); + //此时i等于j,交换基数和i/j,使左边的数小于等于基数,右边的数大于等于基数 + if (start != i) { + ArrayUtil.swap(arr, start, i); } - System.out.println(Arrays.toString(arr)); deal(arr, start, i - 1); deal(arr, j + 1, end); } public static void main(String[] args) { - Integer[] arr = {1, 43, 2, 3, 4, 5, 6, 7, 5, 6, 555, 12, 31, 5, 5}; + Integer[] arr = {1, 43, 2, 7, 5, 6, 555, 200, 21}; deal(arr, 0, arr.length - 1); + System.out.println("结果" + Arrays.toString(arr)); } } diff --git a/3.排序算法/src/sort/exchange/ShellSort.java b/3.排序算法/src/sort/exchange/ShellSort.java new file mode 100644 index 0000000..7786826 --- /dev/null +++ b/3.排序算法/src/sort/exchange/ShellSort.java @@ -0,0 +1,45 @@ +package sort.exchange; + +import java.util.Arrays; + +/** + * 类功能简述:希尔排序 + * 类功能详述:以升序为例 + * 希尔排序也是插入排序的一种,是对上面的直接插入排序的一种改进。因为直接插入排序在数组大致有序时效率较高,如果数组完全逆序的情况 + * 下效率就很慢了,因为一次只能移动一个位置,完全逆序的情况下每次插入都会移动非常多的次数,效率很慢。希尔排序的目的就是一次能够移动多个 + * 位置,减少移动次数。详细过程如下: + * 1. 取一个小于数组长度n的整数n1,将所有间隔为n1的数分成一组,对各组进行直接插入排序.然后n=n1; + * 2. 重复上述操纵,直到n1=1进行一次完整的插入排序后结束。 + *

+ * 总体思想是先一次移动多个位置,让数组整体大致有序,这样当n=1时再直接插入排序速度会快很多。 + * + * @author fanxb + * @date 2019/7/31 17:17 + */ +public class ShellSort { + + public static void sort(Integer[] arr) { + int n1 = arr.length / 2; + // 也可将do/while替换成尾递归 + do { + //共n1组数据需要进行直接插入排序 + for (int start = 0; start < n1; start++) { + //对一组执行插入排序,第一个数为arr[start],增量为n1 + for (int i = start; i < arr.length; i += n1) { + int j = i, temp = arr[i]; + for (; j > start && temp < arr[j - n1]; j -= n1) { + arr[j] = arr[j - n1]; + } + arr[j] = temp; + } + } + n1 /= 2; + } while (n1 > 0); + } + + public static void main(String[] args) { + Integer[] arr = {1, 65, 32, 12, 21}; + ShellSort.sort(arr); + System.out.println(Arrays.toString(arr)); + } +} diff --git a/3.排序算法/src/sort/exchange/SimpleSelectSort.java b/3.排序算法/src/sort/exchange/SimpleSelectSort.java new file mode 100644 index 0000000..ed7e462 --- /dev/null +++ b/3.排序算法/src/sort/exchange/SimpleSelectSort.java @@ -0,0 +1,36 @@ +package sort.exchange; + +import util.ArrayUtil; + +import java.util.Arrays; + +/** + * 类功能简述:简单选择排序 + * 类功能详述:以升序为例 + *

+ * 简单选择排序顾名思义,每次从无序部分选出一个最大的数,和无序部分的最后一个值交换,重复n-1次后所有的值都变成有序状态 + * + * @author fanxb + * @date 2019/7/31 17:49 + */ +public class SimpleSelectSort { + + public static void sort(Integer[] arr) { + int length = arr.length; + for (int i = 0; i < length - 1; i++) { + int maxIndex = 0; + for (int j = 1; j < length - i; j++) { + if (arr[j] > arr[maxIndex]) { + maxIndex = j; + } + } + ArrayUtil.swap(arr, maxIndex, length - i); + } + } + + public static void main(String[] args) { + Integer[] arr = {1, 65, 32, 12, 21}; + ShellSort.sort(arr); + System.out.println(Arrays.toString(arr)); + } +}