From 1692361f7eb3a82dcb6fc5da0c1449ed4ad980aa Mon Sep 17 00:00:00 2001 From: Rico Lin Date: Fri, 26 May 2017 07:59:45 +0800 Subject: [PATCH] =?UTF-8?q?=E6=96=B0=E5=A2=9E=E6=8A=98=E5=8D=8A=E6=8F=92?= =?UTF-8?q?=E5=85=A5=E6=8E=92=E5=BA=8F=E5=92=8C=E5=A0=86=E6=8E=92=E5=BA=8F?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- .../edu/tju/rico/sort/BinaryInsertSort.java | 45 +++++++++++++ src/cn/edu/tju/rico/sort/HeapSort.java | 64 +++++++++++++++++++ src/cn/edu/tju/rico/sort/QuickSort.java | 4 +- src/cn/edu/tju/rico/sort/RadixSort.java | 2 +- .../tju/rico/sort/StraightInsertionSort.java | 12 ++-- src/cn/edu/tju/rico/test/SortTest.java | 16 +++++ 6 files changed, 134 insertions(+), 9 deletions(-) create mode 100644 src/cn/edu/tju/rico/sort/BinaryInsertSort.java create mode 100644 src/cn/edu/tju/rico/sort/HeapSort.java diff --git a/src/cn/edu/tju/rico/sort/BinaryInsertSort.java b/src/cn/edu/tju/rico/sort/BinaryInsertSort.java new file mode 100644 index 0000000..2177c8b --- /dev/null +++ b/src/cn/edu/tju/rico/sort/BinaryInsertSort.java @@ -0,0 +1,45 @@ +package cn.edu.tju.rico.sort; + + +/** + * Title: 插入排序中的折半插入排序,依赖于初始序列 + * Description: 折半搜索出插入位置,并直接插入;与直接插入搜索的区别是,后者的搜索要快于顺序搜索 + * 时间复杂度:折半插入排序比直接插入排序明显减少了关键字之间的比较次数,但是移动次数是没有改变。所以, + * 折半插入排序和插入排序的时间复杂度相同都是O(N^2),在减少了比较次数方面它确实相当优秀,所以该算法仍然比直接插入排序好。 + * 空间复杂度:O(1) + * 稳 定 性:稳定 + * 内部排序(在排序过程中数据元素完全在内存) + * @author rico + * @created 2017年5月25日 下午12:03:23 + */ +public class BinaryInsertSort { + public static int[] binaryInsertSort(int[] target) { + if (target != null && target.length > 1) { + for (int i = 1; i < target.length; i++) { + int left = 0; + int right = i - 1; + int mid; + int temp = target[i]; + if(temp < target[right]){ // 当前值小于有序序列的最大值时,开始查找插入位置 + while(left <= right){ + mid = (left + right)/2; + if(target[mid] < temp){ + left = mid + 1; // 缩小插入区间 + }else if(target[mid] > temp){ + right = mid - 1; // 缩小插入区间 + }else{ // 待插入值与有序序列中的target[mid]相等,保证稳定性的处理 + left = left + 1; + } + } + + // left及其后面的数据顺序向后移动,并在left位置插入 + for (int j = i; j > left; j--) { + target[j] = target[j-1]; + } + target[left] = temp; + } + } + } + return target; + } +} diff --git a/src/cn/edu/tju/rico/sort/HeapSort.java b/src/cn/edu/tju/rico/sort/HeapSort.java new file mode 100644 index 0000000..386eac3 --- /dev/null +++ b/src/cn/edu/tju/rico/sort/HeapSort.java @@ -0,0 +1,64 @@ +package cn.edu.tju.rico.sort; + +/** + * Title: 堆排序(选择排序),升序排序(最大堆) + * Description: 现将给定序列调整为最大堆,然后每次将堆顶元素与堆尾元素交换并缩小堆的范围,直到将堆缩小至1 + * 时间复杂度:O(nlgn) + * 空间复杂度:O(1) + * 稳 定 性:不稳定 + * 内部排序(在排序过程中数据元素完全在内存) + * @author rico + * @created 2017年5月25日 上午9:48:06 + */ +public class HeapSort { + + public static int[] heapSort(int[] target) { + if (target != null && target.length > 1) { + + // 调整为最大堆 + int pos = (target.length - 2) / 2; + while (pos >= 0) { + shiftDown(target, pos, target.length - 1); + pos--; + } + + // 堆排序 + for (int i = target.length-1; i > 0; i--) { + int temp = target[i]; + target[i] = target[0]; + target[0] = temp; + shiftDown(target, 0, i-1); + } + return target; + } + return target; + } + + + /** + * @description 自上而下调整为最大堆 + * @author rico + * @created 2017年5月25日 上午9:45:40 + * @param target + * @param start + * @param end + */ + private static void shiftDown(int[] target, int start, int end) { + int i = start; + int j = 2 * start + 1; + int temp = target[i]; + while (j <= end) { // 迭代条件 + if (j < end && target[j + 1] > target[j]) { //找出较大子女 + j = j + 1; + } + if (target[j] <= temp) { // 父亲大于子女 + break; + } else { + target[i] = target[j]; + i = j; + j = 2 * j + 1; + } + } + target[i] = temp; + } +} diff --git a/src/cn/edu/tju/rico/sort/QuickSort.java b/src/cn/edu/tju/rico/sort/QuickSort.java index f918929..bc174da 100644 --- a/src/cn/edu/tju/rico/sort/QuickSort.java +++ b/src/cn/edu/tju/rico/sort/QuickSort.java @@ -4,7 +4,7 @@ /** * Title: 交换排序中的快速排序,目前应用最为广泛的排序算法,是一个递归算法 - * Description:归并排序包括两个过程:划分 和 快排 + * Description:快速排序包括两个过程:划分 和 快排 * "划分"是指将原序列按基准元素划分两个子序列 * "快排"是指分别对子序列进行快排 * @@ -12,7 +12,7 @@ * * 对大规模数据排序时,快排是快的;对小规模数据排序时,快排是慢的,甚至慢于简单选择排序等简单排序方法 * - * 归并排序依赖于原始序列,因此其时间复杂度从O(nlgn)到O(n^2)不等 + * 快速排序依赖于原始序列,因此其时间复杂度从O(nlgn)到O(n^2)不等 * 时间复杂度:最好情形O(nlgn),平均情形O(nlgn),最差情形O(n^2) * * 递归所消耗的栈空间 diff --git a/src/cn/edu/tju/rico/sort/RadixSort.java b/src/cn/edu/tju/rico/sort/RadixSort.java index 3a0a29b..da4d362 100644 --- a/src/cn/edu/tju/rico/sort/RadixSort.java +++ b/src/cn/edu/tju/rico/sort/RadixSort.java @@ -52,7 +52,7 @@ public static int[] radixSort(int[] target, int r, int d, int n){ } count[j] = 0; // 计数器归零 } - divisor *= 10; //用于获取元素对应位数字 + divisor *= 10; //用于获取元素对应位数字 } } return target; diff --git a/src/cn/edu/tju/rico/sort/StraightInsertionSort.java b/src/cn/edu/tju/rico/sort/StraightInsertionSort.java index db7820c..40a1f44 100644 --- a/src/cn/edu/tju/rico/sort/StraightInsertionSort.java +++ b/src/cn/edu/tju/rico/sort/StraightInsertionSort.java @@ -1,7 +1,7 @@ package cn.edu.tju.rico.sort; /** - * Title: 插入排序中的直接插入排序 + * Title: 插入排序中的直接插入排序 ,依赖于初始序列 * Description: 在有序序列中不断插入新的记录以达到扩大有序区到整个数组的目的 * 时间复杂度:最好情形O(n),平均情形O(n^2),最差情形O(n^2) * 空间复杂度:O(1) @@ -14,10 +14,10 @@ public class StraightInsertionSort { public static int[] insertSort(int[] target){ - if(target != null && target.length != 1){ - for (int i = 1; i < target.length; i++) { - for (int j = i; j > 0; j--) { - if(target[j] < target[j-1]){ + if(target != null && target.length != 1){ // 待排序数组不为空且长度大于1 + for (int i = 1; i < target.length; i++) { // 不断扩大有序序列,直到扩展到整个数组 + for (int j = i; j > 0; j--) { // 向有序序列中插入新的元素 + if(target[j] < target[j-1]){ // 交换 int temp = target[j]; target[j] = target[j-1]; target[j-1] = temp; @@ -27,4 +27,4 @@ public static int[] insertSort(int[] target){ } return target; } -} +} \ No newline at end of file diff --git a/src/cn/edu/tju/rico/test/SortTest.java b/src/cn/edu/tju/rico/test/SortTest.java index e1cb3ce..0529a5d 100644 --- a/src/cn/edu/tju/rico/test/SortTest.java +++ b/src/cn/edu/tju/rico/test/SortTest.java @@ -2,7 +2,9 @@ import java.util.Arrays; +import cn.edu.tju.rico.sort.BinaryInsertSort; import cn.edu.tju.rico.sort.BubbleSort; +import cn.edu.tju.rico.sort.HeapSort; import cn.edu.tju.rico.sort.MergeSort; import cn.edu.tju.rico.sort.QuickSort; import cn.edu.tju.rico.sort.RadixSort; @@ -73,5 +75,19 @@ public static void main(String[] args) { System.out.println("原数组 : " + Arrays.toString(target9)); RadixSort.radixSort(target9,10,2,target9.length); System.out.println(Arrays.toString(target9)); + + System.out.println("\n----------------------\n"); + System.out.println("堆排序 : "); + int[] target10 = { 21, 25, 49, 25, 16, 18, 31, 41 }; + System.out.println("原数组 : " + Arrays.toString(target10)); + HeapSort.heapSort(target10); + System.out.println(Arrays.toString(target10)); + + System.out.println("\n----------------------\n"); + System.out.println("折半插入排序 : "); + int[] target11 = { 21, 25, 49, 25, 16, 18, 31, 41, 21, 9 }; + System.out.println("原数组 : " + Arrays.toString(target11)); + BinaryInsertSort.binaryInsertSort(target11); + System.out.println(Arrays.toString(target11)); } }