diff --git a/.gitignore b/.gitignore index 1a366fb..f6cbc5f 100644 --- a/.gitignore +++ b/.gitignore @@ -13,4 +13,9 @@ _book # eBook build output *.epub *.mobi -*.pdf \ No newline at end of file +*.pdf +\.idea/ + +*.iml + +src/javaSortTest/target/ diff --git a/1.bubbleSort.md b/1.bubbleSort.md index e73bce5..78c3b83 100644 --- a/1.bubbleSort.md +++ b/1.bubbleSort.md @@ -36,7 +36,7 @@ ```js function bubbleSort(arr) { var len = arr.length; - for (var i = 0; i < len; i++) { + for (var i = 0; i < len - 1; i++) { for (var j = 0; j < len - 1 - i; j++) { if (arr[j] > arr[j+1]) { // 相邻元素两两对比 var temp = arr[j+1]; // 元素交换 @@ -61,3 +61,71 @@ def bubbleSort(arr): arr[j], arr[j + 1] = arr[j + 1], arr[j] return arr ``` + +## 7. Go 代码实现 + +```go +func bubbleSort(arr []int) []int { + length := len(arr) + for i := 0; i < length; i++ { + for j := 0; j < length-1-i; j++ { + if arr[j] > arr[j+1] { + arr[j], arr[j+1] = arr[j+1], arr[j] + } + } + } + return arr +} +``` + +## 8. Java 代码实现 + +```java +public class BubbleSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + for (int i = 1; i < arr.length; i++) { + // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。 + boolean flag = true; + + for (int j = 0; j < arr.length - i; j++) { + if (arr[j] > arr[j + 1]) { + int tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + + flag = false; + } + } + + if (flag) { + break; + } + } + return arr; + } +} +``` + +## 9. PHP 代码实现 + +```php +function bubbleSort($arr) +{ + $len = count($arr); + for ($i = 0; $i < $len - 1; $i++) { + for ($j = 0; $j < $len - 1 - $i; $j++) { + if ($arr[$j] > $arr[$j+1]) { + $tmp = $arr[$j]; + $arr[$j] = $arr[$j+1]; + $arr[$j+1] = $tmp; + } + } + } + return $arr; +} +``` diff --git a/10.radixSort.md b/10.radixSort.md index 5f40ea7..0bcd341 100644 --- a/10.radixSort.md +++ b/10.radixSort.md @@ -47,4 +47,126 @@ function radixSort(arr, maxDigit) { } return arr; } +``` + +## 4. Java 代码实现 + +```java +/** + * 基数排序 + * 考虑负数的情况还可以参考: https://code.i-harness.com/zh-CN/q/e98fa9 + */ +public class RadixSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int maxDigit = getMaxDigit(arr); + return radixSort(arr, maxDigit); + } + + /** + * 获取最高位数 + */ + private int getMaxDigit(int[] arr) { + int maxValue = getMaxValue(arr); + return getNumLenght(maxValue); + } + + private int getMaxValue(int[] arr) { + int maxValue = arr[0]; + for (int value : arr) { + if (maxValue < value) { + maxValue = value; + } + } + return maxValue; + } + + protected int getNumLenght(long num) { + if (num == 0) { + return 1; + } + int lenght = 0; + for (long temp = num; temp != 0; temp /= 10) { + lenght++; + } + return lenght; + } + + private int[] radixSort(int[] arr, int maxDigit) { + int mod = 10; + int dev = 1; + + for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) { + // 考虑负数的情况,这里扩展一倍队列数,其中 [0-9]对应负数,[10-19]对应正数 (bucket + 10) + int[][] counter = new int[mod * 2][0]; + + for (int j = 0; j < arr.length; j++) { + int bucket = ((arr[j] % mod) / dev) + mod; + counter[bucket] = arrayAppend(counter[bucket], arr[j]); + } + + int pos = 0; + for (int[] bucket : counter) { + for (int value : bucket) { + arr[pos++] = value; + } + } + } + + return arr; + } + + /** + * 自动扩容,并保存数据 + * + * @param arr + * @param value + */ + private int[] arrayAppend(int[] arr, int value) { + arr = Arrays.copyOf(arr, arr.length + 1); + arr[arr.length - 1] = value; + return arr; + } +} +``` + +## 5. PHP 代码实现 + +```php +function radixSort($arr, $maxDigit = null) +{ + if ($maxDigit === null) { + $maxDigit = max($arr); + } + $counter = []; + for ($i = 0; $i < $maxDigit; $i++) { + for ($j = 0; $j < count($arr); $j++) { + preg_match_all('/\d/', (string) $arr[$j], $matches); + $numArr = $matches[0]; + $lenTmp = count($numArr); + $bucket = array_key_exists($lenTmp - $i - 1, $numArr) + ? intval($numArr[$lenTmp - $i - 1]) + : 0; + if (!array_key_exists($bucket, $counter)) { + $counter[$bucket] = []; + } + $counter[$bucket][] = $arr[$j]; + } + $pos = 0; + for ($j = 0; $j < count($counter); $j++) { + $value = null; + if ($counter[$j] !== null) { + while (($value = array_shift($counter[$j])) !== null) { + $arr[$pos++] = $value; + } + } + } + } + + return $arr; +} ``` \ No newline at end of file diff --git a/2.selectionSort.md b/2.selectionSort.md index e471732..103830e 100644 --- a/2.selectionSort.md +++ b/2.selectionSort.md @@ -1,6 +1,6 @@ # 选择排序 -选择排序是一种简单直观的排序算法,是表现最稳定的排序算法之一,因为无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。 +选择排序是一种简单直观的排序算法,无论什么数据进去都是 O(n²) 的时间复杂度。所以用到它的时候,数据规模越小越好。唯一的好处可能就是不占用额外的内存空间了吧。 ## 1. 算法步骤 @@ -42,9 +42,87 @@ function selectionSort(arr) { ```python def selectionSort(arr): - for i in range(len(arr)-1): - for j in range(i+1, len(arr)): - if arr[j] < arr[i]: - arr[i], arr[j] = arr[j], arr[i] + for i in range(len(arr) - 1): + # 记录最小数的索引 + minIndex = i + for j in range(i + 1, len(arr)): + if arr[j] < arr[minIndex]: + minIndex = j + # i 不是最小数时,将 i 和最小数进行交换 + if i != minIndex: + arr[i], arr[minIndex] = arr[minIndex], arr[i] return arr ``` + +## 5. Go 代码实现 + +```go +func selectionSort(arr []int) []int { + length := len(arr) + for i := 0; i < length-1; i++ { + min := i + for j := i + 1; j < length; j++ { + if arr[min] > arr[j] { + min = j + } + } + arr[i], arr[min] = arr[min], arr[i] + } + return arr +} +``` + +## 6. Java 代码实现 + +```java +public class SelectionSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + // 总共要经过 N-1 轮比较 + for (int i = 0; i < arr.length - 1; i++) { + int min = i; + + // 每轮需要比较的次数 N-i + for (int j = i + 1; j < arr.length; j++) { + if (arr[j] < arr[min]) { + // 记录目前能找到的最小值元素的下标 + min = j; + } + } + + // 将找到的最小值和i位置所在的值进行交换 + if (i != min) { + int tmp = arr[i]; + arr[i] = arr[min]; + arr[min] = tmp; + } + + } + return arr; + } +} +``` + +## 7. PHP 代码实现 + +```php +function selectionSort($arr) +{ + $len = count($arr); + for ($i = 0; $i < $len - 1; $i++) { + $minIndex = $i; + for ($j = $i + 1; $j < $len; $j++) { + if ($arr[$j] < $arr[$minIndex]) { + $minIndex = $j; + } + } + $temp = $arr[$i]; + $arr[$i] = $arr[$minIndex]; + $arr[$minIndex] = $temp; + } + return $arr; +} +``` diff --git a/3.insertionSort.md b/3.insertionSort.md index 008bbd1..c828cb3 100644 --- a/3.insertionSort.md +++ b/3.insertionSort.md @@ -49,3 +49,72 @@ def insertionSort(arr): arr[preIndex+1] = current return arr ``` + +## 5. Go 代码实现 +```go +func insertionSort(arr []int) []int { + for i := range arr { + preIndex := i - 1 + current := arr[i] + for preIndex >= 0 && arr[preIndex] > current { + arr[preIndex+1] = arr[preIndex] + preIndex -= 1 + } + arr[preIndex+1] = current + } + return arr +} +``` + +## 6. Java 代码实现 + +```java +public class InsertSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的 + for (int i = 1; i < arr.length; i++) { + + // 记录要插入的数据 + int tmp = arr[i]; + + // 从已经排序的序列最右边的开始比较,找到比其小的数 + int j = i; + while (j > 0 && tmp < arr[j - 1]) { + arr[j] = arr[j - 1]; + j--; + } + + // 存在比其小的数,插入 + if (j != i) { + arr[j] = tmp; + } + + } + return arr; + } +} +``` + +## 7. PHP 代码实现 + +```php +function insertionSort($arr) +{ + $len = count($arr); + for ($i = 1; $i < $len; $i++) { + $preIndex = $i - 1; + $current = $arr[$i]; + while($preIndex >= 0 && $arr[$preIndex] > $current) { + $arr[$preIndex+1] = $arr[$preIndex]; + $preIndex--; + } + $arr[$preIndex+1] = $current; + } + return $arr; +} +``` diff --git a/4.shellSort.md b/4.shellSort.md index a41c1eb..187ac0e 100644 --- a/4.shellSort.md +++ b/4.shellSort.md @@ -4,15 +4,15 @@ 希尔排序是基于插入排序的以下两点性质而提出改进方法的: - - 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率 - - 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位 + - 插入排序在对几乎已经排好序的数据操作时,效率高,即可以达到线性排序的效率; + - 但插入排序一般来说是低效的,因为插入排序每次只能将数据移动一位; 希尔排序的基本思想是:先将整个待排序的记录序列分割成为若干子序列分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行依次直接插入排序。 ## 1. 算法步骤 -1. 选择一个增量序列 t1,t2,…,tk,其中 ti > tj,tk=1; +1. 选择一个增量序列 t1,t2,……,tk,其中 ti > tj, tk = 1; 2. 按增量序列个数 k,对序列进行 k 趟排序; @@ -62,3 +62,85 @@ def shellSort(arr): return arr } ``` + +## 4. Go 代码实现 + +```go +func shellSort(arr []int) []int { + length := len(arr) + gap := 1 + for gap < gap/3 { + gap = gap*3 + 1 + } + for gap > 0 { + for i := gap; i < length; i++ { + temp := arr[i] + j := i - gap + for j >= 0 && arr[j] > temp { + arr[j+gap] = arr[j] + j -= gap + } + arr[j+gap] = temp + } + gap = gap / 3 + } + return arr +} +``` + +## 5. Java 代码实现 + +```java +public class ShellSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int gap = 1; + while (gap < arr.length) { + gap = gap * 3 + 1; + } + + while (gap > 0) { + for (int i = gap; i < arr.length; i++) { + int tmp = arr[i]; + int j = i - gap; + while (j >= 0 && arr[j] > tmp) { + arr[j + gap] = arr[j]; + j -= gap; + } + arr[j + gap] = tmp; + } + gap = (int) Math.floor(gap / 3); + } + + return arr; + } +} +``` + +## 6. PHP 代码实现 + +```php +function shellSort($arr) +{ + $len = count($arr); + $temp = 0; + $gap = 1; + while($gap < $len / 3) { + $gap = $gap * 3 + 1; + } + for ($gap; $gap > 0; $gap = floor($gap / 3)) { + for ($i = $gap; $i < $len; $i++) { + $temp = $arr[$i]; + for ($j = $i - $gap; $j >= 0 && $arr[$j] > $temp; $j -= $gap) { + $arr[$j+$gap] = $arr[$j]; + } + $arr[$j+$gap] = $temp; + } + } + return $arr; +} +``` diff --git a/5.mergeSort.md b/5.mergeSort.md index f9eb090..bf0de32 100644 --- a/5.mergeSort.md +++ b/5.mergeSort.md @@ -9,8 +9,8 @@ 在《数据结构与算法 JavaScript 描述》中,作者给出了自下而上的迭代方法。但是对于递归法,作者却认为: > However, it is not possible to do so in JavaScript, as the recursion goes too deep for the language to handle. -> -> 然而,在 JavaScript 中这种方式不太可行,因为这个算法的递归深度对它来讲太深了。 +> +> 然而,在 JavaScript 中这种方式不太可行,因为这个算法的递归深度对它来讲太深了。 说实话,我不太理解这句话。意思是 JavaScript 编译器内存太小,递归太深容易造成内存溢出吗?还望有大神能够指教。 @@ -96,3 +96,130 @@ def merge(left,right): result.append(right.pop(0)); return result ``` + +## 6. Go 代码实现 + +```go +func mergeSort(arr []int) []int { + length := len(arr) + if length < 2 { + return arr + } + middle := length / 2 + left := arr[0:middle] + right := arr[middle:] + return merge(mergeSort(left), mergeSort(right)) +} + +func merge(left []int, right []int) []int { + var result []int + for len(left) != 0 && len(right) != 0 { + if left[0] <= right[0] { + result = append(result, left[0]) + left = left[1:] + } else { + result = append(result, right[0]) + right = right[1:] + } + } + + for len(left) != 0 { + result = append(result, left[0]) + left = left[1:] + } + + for len(right) != 0 { + result = append(result, right[0]) + right = right[1:] + } + + return result +} +``` + +## 7. Java 代码实现 + +```java +public class MergeSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + if (arr.length < 2) { + return arr; + } + int middle = (int) Math.floor(arr.length / 2); + + int[] left = Arrays.copyOfRange(arr, 0, middle); + int[] right = Arrays.copyOfRange(arr, middle, arr.length); + + return merge(sort(left), sort(right)); + } + + protected int[] merge(int[] left, int[] right) { + int[] result = new int[left.length + right.length]; + int i = 0; + while (left.length > 0 && right.length > 0) { + if (left[0] <= right[0]) { + result[i++] = left[0]; + left = Arrays.copyOfRange(left, 1, left.length); + } else { + result[i++] = right[0]; + right = Arrays.copyOfRange(right, 1, right.length); + } + } + + while (left.length > 0) { + result[i++] = left[0]; + left = Arrays.copyOfRange(left, 1, left.length); + } + + while (right.length > 0) { + result[i++] = right[0]; + right = Arrays.copyOfRange(right, 1, right.length); + } + + return result; + } + +} +``` + +## 8. PHP 代码实现 + +```php +function mergeSort($arr) +{ + $len = count($arr); + if ($len < 2) { + return $arr; + } + $middle = floor($len / 2); + $left = array_slice($arr, 0, $middle); + $right = array_slice($arr, $middle); + return merge(mergeSort($left), mergeSort($right)); +} + +function merge($left, $right) +{ + $result = []; + + while (count($left) > 0 && count($right) > 0) { + if ($left[0] <= $right[0]) { + $result[] = array_shift($left); + } else { + $result[] = array_shift($right); + } + } + + while (count($left)) + $result[] = array_shift($left); + + while (count($right)) + $result[] = array_shift($right); + + return $result; +} +``` \ No newline at end of file diff --git a/6.quickSort.md b/6.quickSort.md index 01f410d..28ad477 100644 --- a/6.quickSort.md +++ b/6.quickSort.md @@ -6,7 +6,7 @@ 快速排序又是一种分而治之思想在排序算法上的典型应用。本质上来看,快速排序应该算是在冒泡排序基础上的递归分治法。 -快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高! 它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案: +快速排序的名字起的是简单粗暴,因为一听到这个名字你就知道它存在的意义,就是快,而且效率高!它是处理大数据最快的排序算法之一了。虽然 Worst Case 的时间复杂度达到了 O(n²),但是人家就是优秀,在大多数情况下都比平均时间复杂度为 O(n logn) 的排序算法表现要更好,可是这是为什么呢,我也不知道。好在我的强迫症又犯了,查了 N 多资料终于在《算法艺术与信息学竞赛》上找到了满意的答案: > 快速排序的最坏运行情况是 O(n²),比如说顺序数列的快排。但它的平摊期望时间是 O(nlogn),且 O(nlogn) 记号中隐含的常数因子很小,比复杂度稳定等于 O(nlogn) 的归并排序要小很多。所以,对绝大多数顺序性较弱的随机数列而言,快速排序总是优于归并排序。 @@ -15,9 +15,9 @@ 1. 从数列中挑出一个元素,称为 “基准”(pivot); -2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作; +2. 重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作; -3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序; +3. 递归地(recursive)把小于基准值元素的子数列和大于基准值元素的子数列排序; 递归的最底部情形,是数列的大小是零或一,也就是永远都已经被排序好了。虽然一直递归下去,但是这个算法总会退出,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最后的位置去。 @@ -62,6 +62,31 @@ function swap(arr, i, j) { arr[i] = arr[j]; arr[j] = temp; } +function partition2(arr, low, high) { + let pivot = arr[low]; + while (low < high) { + while (low < high && arr[high] > pivot) { + --high; + } + arr[low] = arr[high]; + while (low < high && arr[low] <= pivot) { + ++low; + } + arr[high] = arr[low]; + } + arr[low] = pivot; + return low; +} + +function quickSort2(arr, low, high) { + if (low < high) { + let pivot = partition2(arr, low, high); + quickSort2(arr, low, pivot - 1); + quickSort2(arr, pivot + 1, high); + } + return arr; +} + ``` @@ -92,3 +117,139 @@ def partition(arr, left, right): def swap(arr, i, j): arr[i], arr[j] = arr[j], arr[i] ``` + +## 5. Go 代码实现 + +```go +func quickSort(arr []int) []int { + return _quickSort(arr, 0, len(arr)-1) +} + +func _quickSort(arr []int, left, right int) []int { + if left < right { + partitionIndex := partition(arr, left, right) + _quickSort(arr, left, partitionIndex-1) + _quickSort(arr, partitionIndex+1, right) + } + return arr +} + +func partition(arr []int, left, right int) int { + pivot := left + index := pivot + 1 + + for i := index; i <= right; i++ { + if arr[i] < arr[pivot] { + swap(arr, i, index) + index += 1 + } + } + swap(arr, pivot, index-1) + return index - 1 +} + +func swap(arr []int, i, j int) { + arr[i], arr[j] = arr[j], arr[i] +} +``` + +## 6. C++版 + + +```C++ + //严蔚敏《数据结构》标准分割函数 + Paritition1(int A[], int low, int high) { + int pivot = A[low]; + while (low < high) { + while (low < high && A[high] >= pivot) { + --high; + } + A[low] = A[high]; + while (low < high && A[low] <= pivot) { + ++low; + } + A[high] = A[low]; + } + A[low] = pivot; + return low; + } + + void QuickSort(int A[], int low, int high) //快排母函数 + { + if (low < high) { + int pivot = Paritition1(A, low, high); + QuickSort(A, low, pivot - 1); + QuickSort(A, pivot + 1, high); + } + } +``` + +## 7. Java 代码实现 + +```java +public class QuickSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + return quickSort(arr, 0, arr.length - 1); + } + + private int[] quickSort(int[] arr, int left, int right) { + if (left < right) { + int partitionIndex = partition(arr, left, right); + quickSort(arr, left, partitionIndex - 1); + quickSort(arr, partitionIndex + 1, right); + } + return arr; + } + + private int partition(int[] arr, int left, int right) { + // 设定基准值(pivot) + int pivot = left; + int index = pivot + 1; + for (int i = index; i <= right; i++) { + if (arr[i] < arr[pivot]) { + swap(arr, i, index); + index++; + } + } + swap(arr, pivot, index - 1); + return index - 1; + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} +``` + +## 8. PHP 代码实现 + +```php +function quickSort($arr) +{ + if (count($arr) <= 1) + return $arr; + $middle = $arr[0]; + $leftArray = array(); + $rightArray = array(); + + for ($i = 1; $i < count($arr); $i++) { + if ($arr[$i] > $middle) + $rightArray[] = $arr[$i]; + else + $leftArray[] = $arr[$i]; + } + $leftArray = quickSort($leftArray); + $leftArray[] = $middle; + + $rightArray = quickSort($rightArray); + return array_merge($leftArray, $rightArray); +} +``` diff --git a/7.heapSort.md b/7.heapSort.md index a6a91d8..35b24ec 100644 --- a/7.heapSort.md +++ b/7.heapSort.md @@ -10,7 +10,7 @@ ## 1. 算法步骤 -1. 创建一个堆 H[0..n-1]; +1. 创建一个堆 H[0……n-1]; 2. 把堆首(最大值)和堆尾互换; @@ -106,3 +106,152 @@ def heapSort(arr): heapify(arr, 0) return arr ``` + +## 5. Go 代码实现 + +```go +func heapSort(arr []int) []int { + arrLen := len(arr) + buildMaxHeap(arr, arrLen) + for i := arrLen - 1; i >= 0; i-- { + swap(arr, 0, i) + arrLen -= 1 + heapify(arr, 0, arrLen) + } + return arr +} + +func buildMaxHeap(arr []int, arrLen int) { + for i := arrLen / 2; i >= 0; i-- { + heapify(arr, i, arrLen) + } +} + +func heapify(arr []int, i, arrLen int) { + left := 2*i + 1 + right := 2*i + 2 + largest := i + if left < arrLen && arr[left] > arr[largest] { + largest = left + } + if right < arrLen && arr[right] > arr[largest] { + largest = right + } + if largest != i { + swap(arr, i, largest) + heapify(arr, largest, arrLen) + } +} + +func swap(arr []int, i, j int) { + arr[i], arr[j] = arr[j], arr[i] +} +``` + +## 6. Java 代码实现 + +```java +public class HeapSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int len = arr.length; + + buildMaxHeap(arr, len); + + for (int i = len - 1; i > 0; i--) { + swap(arr, 0, i); + len--; + heapify(arr, 0, len); + } + return arr; + } + + private void buildMaxHeap(int[] arr, int len) { + for (int i = (int) Math.floor(len / 2); i >= 0; i--) { + heapify(arr, i, len); + } + } + + private void heapify(int[] arr, int i, int len) { + int left = 2 * i + 1; + int right = 2 * i + 2; + int largest = i; + + if (left < len && arr[left] > arr[largest]) { + largest = left; + } + + if (right < len && arr[right] > arr[largest]) { + largest = right; + } + + if (largest != i) { + swap(arr, i, largest); + heapify(arr, largest, len); + } + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} +``` + +## 7. PHP 代码实现 + +```php +function buildMaxHeap(&$arr) +{ + global $len; + for ($i = floor($len/2); $i >= 0; $i--) { + heapify($arr, $i); + } +} + +function heapify(&$arr, $i) +{ + global $len; + $left = 2 * $i + 1; + $right = 2 * $i + 2; + $largest = $i; + + if ($left < $len && $arr[$left] > $arr[$largest]) { + $largest = $left; + } + + if ($right < $len && $arr[$right] > $arr[$largest]) { + $largest = $right; + } + + if ($largest != $i) { + swap($arr, $i, $largest); + heapify($arr, $largest); + } +} + +function swap(&$arr, $i, $j) +{ + $temp = $arr[$i]; + $arr[$i] = $arr[$j]; + $arr[$j] = $temp; +} + +function heapSort($arr) { + global $len; + $len = count($arr); + buildMaxHeap($arr); + for ($i = count($arr) - 1; $i > 0; $i--) { + swap($arr, 0, $i); + $len--; + heapify($arr, 0); + } + return $arr; +} +``` \ No newline at end of file diff --git a/8.countingSort.md b/8.countingSort.md index 4d8f41b..efabf9c 100644 --- a/8.countingSort.md +++ b/8.countingSort.md @@ -54,3 +54,104 @@ def countingSort(arr, maxValue): bucket[j]-=1 return arr ``` + +## 4. Go 代码实现 + +```go +func countingSort(arr []int, maxValue int) []int { + bucketLen := maxValue + 1 + bucket := make([]int, bucketLen) // 初始为0的数组 + + sortedIndex := 0 + length := len(arr) + + for i := 0; i < length; i++ { + bucket[arr[i]] += 1 + } + + for j := 0; j < bucketLen; j++ { + for bucket[j] > 0 { + arr[sortedIndex] = j + sortedIndex += 1 + bucket[j] -= 1 + } + } + + return arr +} +``` + +## 5. Java 代码实现 + +```java +public class CountingSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int maxValue = getMaxValue(arr); + + return countingSort(arr, maxValue); + } + + private int[] countingSort(int[] arr, int maxValue) { + int bucketLen = maxValue + 1; + int[] bucket = new int[bucketLen]; + + for (int value : arr) { + bucket[value]++; + } + + int sortedIndex = 0; + for (int j = 0; j < bucketLen; j++) { + while (bucket[j] > 0) { + arr[sortedIndex++] = j; + bucket[j]--; + } + } + return arr; + } + + private int getMaxValue(int[] arr) { + int maxValue = arr[0]; + for (int value : arr) { + if (maxValue < value) { + maxValue = value; + } + } + return maxValue; + } + +} +``` + +## 6. PHP 代码实现 + +```php +function countingSort($arr, $maxValue = null) +{ + if ($maxValue === null) { + $maxValue = max($arr); + } + for ($m = 0; $m < $maxValue + 1; $m++) { + $bucket[] = null; + } + + $arrLen = count($arr); + for ($i = 0; $i < $arrLen; $i++) { + if (!array_key_exists($arr[$i], $bucket)) { + $bucket[$arr[$i]] = 0; + } + $bucket[$arr[$i]]++; + } + + $sortedIndex = 0; + foreach ($bucket as $key => $len) { + if ($len !== null) $arr[$sortedIndex++] = $key; + } + + return $arr; +} +``` \ No newline at end of file diff --git a/9.bucketSort.md b/9.bucketSort.md index 30966f4..bd76a63 100644 --- a/9.bucketSort.md +++ b/9.bucketSort.md @@ -61,4 +61,115 @@ function bucketSort(arr, bucketSize) { return arr; } +``` + +## 4. Java 代码实现 + +```java +public class BucketSort implements IArraySort { + + private static final InsertSort insertSort = new InsertSort(); + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + return bucketSort(arr, 5); + } + + private int[] bucketSort(int[] arr, int bucketSize) throws Exception { + if (arr.length == 0) { + return arr; + } + + int minValue = arr[0]; + int maxValue = arr[0]; + for (int value : arr) { + if (value < minValue) { + minValue = value; + } else if (value > maxValue) { + maxValue = value; + } + } + + int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1; + int[][] buckets = new int[bucketCount][0]; + + // 利用映射函数将数据分配到各个桶中 + for (int i = 0; i < arr.length; i++) { + int index = (int) Math.floor((arr[i] - minValue) / bucketSize); + buckets[index] = arrAppend(buckets[index], arr[i]); + } + + int arrIndex = 0; + for (int[] bucket : buckets) { + if (bucket.length <= 0) { + continue; + } + // 对每个桶进行排序,这里使用了插入排序 + bucket = insertSort.sort(bucket); + for (int value : bucket) { + arr[arrIndex++] = value; + } + } + + return arr; + } + + /** + * 自动扩容,并保存数据 + * + * @param arr + * @param value + */ + private int[] arrAppend(int[] arr, int value) { + arr = Arrays.copyOf(arr, arr.length + 1); + arr[arr.length - 1] = value; + return arr; + } + +} +``` + +## 5. PHP 代码实现 + +```php +function bucketSort($arr, $bucketSize = 5) +{ + if (count($arr) === 0) { + return $arr; + } + + $minValue = $arr[0]; + $maxValue = $arr[0]; + for ($i = 1; $i < count($arr); $i++) { + if ($arr[$i] < $minValue) { + $minValue = $arr[$i]; + } else if ($arr[$i] > $maxValue) { + $maxValue = $arr[$i]; + } + } + + $bucketCount = floor(($maxValue - $minValue) / $bucketSize) + 1; + $buckets = array(); + for ($i = 0; $i < count($buckets); $i++) { + $buckets[$i] = []; + } + + for ($i = 0; $i < count($arr); $i++) { + $buckets[floor(($arr[$i] - $minValue) / $bucketSize)][] = $arr[$i]; + } + + $arr = array(); + for ($i = 0; $i < count($buckets); $i++) { + $bucketTmp = $buckets[$i]; + sort($bucketTmp); + for ($j = 0; $j < count($bucketTmp); $j++) { + $arr[] = $bucketTmp[$j]; + } + } + + return $arr; +} ``` \ No newline at end of file diff --git a/README.md b/README.md index d8df556..a14f9c1 100644 --- a/README.md +++ b/README.md @@ -12,7 +12,7 @@ **关于时间复杂度**: 1. 平方阶 (O(n2)) 排序 - 各类简单排序:直接插入、直接选择和冒泡排序。 + 各类简单排序:直接插入、直接选择和冒泡排序。 2. 线性对数阶 (O(nlog2n)) 排序 快速排序、堆排序和归并排序; 3. O(n1+§)) 排序,§ 是介于 0 和 1 之间的常数。 @@ -62,4 +62,6 @@ 开源项目地址:[https://github.com/hustcc/JS-Sorting-Algorithm](https://github.com/hustcc/JS-Sorting-Algorithm),整理人 [hustcc](https://github.com/hustcc)。 -GitHook 在线阅读地址:[https://sort.hust.cc/](https://sort.hust.cc/)。 \ No newline at end of file +GitBook 在线阅读地址:[https://sort.hust.cc/](https://sort.hust.cc/)。 + +本项目使用 [hint](https://github.com/hustcc/hint) 进行中文 Markdown 文件的格式检查,务必在提交 Pr 之前,保证 Markdown 格式正确。 diff --git a/pythonSortTest.py b/pythonSortTest.py deleted file mode 100644 index eb5b137..0000000 --- a/pythonSortTest.py +++ /dev/null @@ -1,165 +0,0 @@ -''' -# Create by LokiSharp(loki.sharp#gmail) at 2017-1-22 -''' - -TOTAL=5000 - -def sortTest(func, total=1000): - import random, copy, operator, math, time - arrList = [i for i in range(-math.floor(total/2),math.ceil(total/2))] - arrListR = copy.deepcopy(arrList) - while operator.eq(arrList,arrListR): - random.shuffle(arrListR) - #print("--- [Origin List]", arrList, "Use", func.__name__,"with Total:", len(arrList)) - #print("--> [Random List]", arrListR, "Use", func.__name__,"with Total:", len(arrList)) - start = time.clock() - arrListR = func(arrListR) - end = time.clock() - runtime = end-start - #print("--> [Sorted List]", arrListR, "Use", func.__name__,"with Total:", len(arrList)) - if operator.eq(arrList, arrListR): - print("[Success]", func.__name__,"with Total:", len(arrList),"in %.5fs" % runtime) - return True - else: - print("[Fail]", func.__name__,"with Total:", len(arrList),"in %.5fs" % runtime) - return False - -def bubbleSort(arr): - for i in range(1, len(arr)): - for j in range(0, len(arr)-i): - if arr[j] > arr[j+1]: - arr[j], arr[j + 1] = arr[j + 1], arr[j] - return arr - -def selectionSort(arr): - for i in range(len(arr)-1): - for j in range(i+1, len(arr)): - if arr[j] < arr[i]: - arr[i], arr[j] = arr[j], arr[i] - return arr - -def insertionSort(arr): - for i in range(len(arr)): - preIndex = i-1 - current = arr[i] - while preIndex >= 0 and arr[preIndex] > current: - arr[preIndex+1] = arr[preIndex] - preIndex-=1 - arr[preIndex+1] = current - return arr - -def shellSort(arr): - import math - gap=1 - while(gap < len(arr)/3): - gap = gap*3+1 - while gap > 0: - for i in range(gap,len(arr)): - temp = arr[i] - j = i-gap - while j >=0 and arr[j] > temp: - arr[j+gap]=arr[j] - j-=gap - arr[j+gap] = temp - gap = math.floor(gap/3) - return arr - -def mergeSort(arr): - import math - if(len(arr)<2): - return arr - middle = math.floor(len(arr)/2) - left, right = arr[0:middle], arr[middle:] - return merge(mergeSort(left), mergeSort(right)) - -def merge(left,right): - result = [] - while left and right: - if left[0] <= right[0]: - result.append(left.pop(0)); - else: - result.append(right.pop(0)); - while left: - result.append(left.pop(0)); - while right: - result.append(right.pop(0)); - return result - -def quickSort(arr, left=None, right=None): - left = 0 if not isinstance(left,(int, float)) else left - right = len(arr)-1 if not isinstance(right,(int, float)) else right - if left < right: - partitionIndex = partition(arr, left, right) - quickSort(arr, left, partitionIndex-1) - quickSort(arr, partitionIndex+1, right) - return arr - -def partition(arr, left, right): - pivot = left - index = pivot+1 - i = index - while i <= right: - if arr[i] < arr[pivot]: - swap(arr, i, index) - index+=1 - i+=1 - swap(arr,pivot,index-1) - return index-1 - -def swap(arr, i, j): - arr[i], arr[j] = arr[j], arr[i] - -def buildMaxHeap(arr): - import math - for i in range(math.floor(len(arr)/2),-1,-1): - heapify(arr,i) - -def heapify(arr, i): - left = 2*i+1 - right = 2*i+2 - largest = i - if left < arrLen and arr[left] > arr[largest]: - largest = left - if right < arrLen and arr[right] > arr[largest]: - largest = right - - if largest != i: - swap(arr, i, largest) - heapify(arr, largest) - -def swap(arr, i, j): - arr[i], arr[j] = arr[j], arr[i] - -def heapSort(arr): - global arrLen - arrLen = len(arr) - buildMaxHeap(arr) - for i in range(len(arr)-1,0,-1): - swap(arr,0,i) - arrLen -=1 - heapify(arr, 0) - return arr - -def countingSort(arr, maxValue=None): - bucketLen = maxValue+1 - bucket = [0]*bucketLen - sortedIndex =0 - arrLen = len(arr) - for i in range(arrLen): - if not bucket[arr[i]]: - bucket[arr[i]]=0 - bucket[arr[i]]+=1 - for j in range(bucketLen): - while bucket[j]>0: - arr[sortedIndex] = j - sortedIndex+=1 - bucket[j]-=1 - return arr - -sortTest(bubbleSort, TOTAL) -sortTest(selectionSort, TOTAL) -sortTest(insertionSort, TOTAL) -sortTest(shellSort, TOTAL) -sortTest(mergeSort, TOTAL) -sortTest(quickSort, TOTAL) -sortTest(heapSort, TOTAL) diff --git a/src/goSortTest.go b/src/goSortTest.go new file mode 100644 index 0000000..3738cf0 --- /dev/null +++ b/src/goSortTest.go @@ -0,0 +1,240 @@ +package main + +import ( + "fmt" + "math/rand" + "time" +) + +/* global varialbe for heapsort*/ +var arrLen int + +// 初始化 array with num +func initArray(num int) []int { + if num < 1 { + panic("num must bigger than 1") + } + + arr := make([]int, num) + middle := num / 2 + // fmt.Println("middle :", middle) + for i, _ := range arr { + arr[i] = i - middle + } + return arr +} + +// 比较 sort 前后数组是否相同 +func compare(arr1 []int, arr2 []int) bool { + if len(arr1) != len(arr2) { + return false + } + + for i, _ := range arr1 { + if arr1[i] != arr2[i] { + return false + } + } + + return true +} + +// 测试 sort func 是否有效 +func test_func(num int, sort func(arr []int) []int) { + r := rand.New(rand.NewSource(time.Now().UnixNano())) + src := initArray(num) + dest := make([]int, len(src)) + perm := r.Perm(len(src)) + for i, v := range perm { + dest[v] = src[i] + } + + // fmt.Println(src) + // fmt.Println(dest) + result := sort(dest) + // fmt.Println(result) + + if compare(src, result) { + fmt.Println("Test passed") + } else { + fmt.Println("Test failed") + } +} + +// bubble sort +func bubbleSort(arr []int) []int { + length := len(arr) + for i := 0; i < length; i++ { + for j := 0; j < length-1-i; j++ { + if arr[j] > arr[j+1] { + arr[j], arr[j+1] = arr[j+1], arr[j] + } + } + } + return arr +} + +// selection sort +func selectionSort(arr []int) []int { + length := len(arr) + for i := 0; i < length-1; i++ { + min := i + for j := i + 1; j < length; j++ { + if arr[min] > arr[j] { + min = j + } + } + arr[i], arr[min] = arr[min], arr[i] + } + return arr +} + +// insertion sort +func insertionSort(arr []int) []int { + for i := range arr { + preIndex := i - 1 + current := arr[i] + for preIndex >= 0 && arr[preIndex] > current { + arr[preIndex+1] = arr[preIndex] + preIndex -= 1 + } + arr[preIndex+1] = current + } + return arr +} + +// shellsort +func shellSort(arr []int) []int { + length := len(arr) + gap := 1 + for gap < gap/3 { + gap = gap*3 + 1 + } + for gap > 0 { + for i := gap; i < length; i++ { + temp := arr[i] + j := i - gap + for j >= 0 && arr[j] > temp { + arr[j+gap] = arr[j] + j -= gap + } + arr[j+gap] = temp + } + gap = gap / 3 + } + return arr +} + +// merge sort +func mergeSort(arr []int) []int { + length := len(arr) + if length < 2 { + return arr + } + middle := length / 2 + left := arr[0:middle] + right := arr[middle:] + return merge(mergeSort(left), mergeSort(right)) +} + +func merge(left []int, right []int) []int { + var result []int + for len(left) != 0 && len(right) != 0 { + if left[0] <= right[0] { + result = append(result, left[0]) + left = left[1:] + } else { + result = append(result, right[0]) + right = right[1:] + } + } + + for len(left) != 0 { + result = append(result, left[0]) + left = left[1:] + } + + for len(right) != 0 { + result = append(result, right[0]) + right = right[1:] + } + + return result +} + +// quicksort +func quickSort(arr []int) []int { + return _quickSort(arr, 0, len(arr)-1) +} + +func _quickSort(arr []int, left, right int) []int { + if left < right { + partitionIndex := partition(arr, left, right) + _quickSort(arr, left, partitionIndex-1) + _quickSort(arr, partitionIndex+1, right) + } + return arr +} + +func partition(arr []int, left, right int) int { + pivot := left + index := pivot + 1 + + for i := index; i <= right; i++ { + if arr[i] < arr[pivot] { + swap(arr, i, index) + index += 1 + } + } + swap(arr, pivot, index-1) + return index - 1 +} + +// heap sort +func heapSort(arr []int) []int { + arrLen := len(arr) + buildMaxHeap(arr, arrLen) + for i := arrLen - 1; i >= 0; i-- { + swap(arr, 0, i) + arrLen -= 1 + heapify(arr, 0, arrLen) + } + return arr +} + +func buildMaxHeap(arr []int, arrLen int) { + for i := arrLen / 2; i >= 0; i-- { + heapify(arr, i, arrLen) + } +} + +func heapify(arr []int, i, arrLen int) { + left := 2*i + 1 + right := 2*i + 2 + largest := i + if left < arrLen && arr[left] > arr[largest] { + largest = left + } + if right < arrLen && arr[right] > arr[largest] { + largest = right + } + if largest != i { + swap(arr, i, largest) + heapify(arr, largest, arrLen) + } +} + +func swap(arr []int, i, j int) { + arr[i], arr[j] = arr[j], arr[i] +} + +func main() { + num := 5000 + test_func(num, bubbleSort) + test_func(num, selectionSort) + test_func(num, insertionSort) + test_func(num, shellSort) + test_func(num, mergeSort) + test_func(num, quickSort) + test_func(num, heapSort) +} diff --git a/src/java/main/BubbleSort.java b/src/java/main/BubbleSort.java new file mode 100644 index 0000000..3c8cebc --- /dev/null +++ b/src/java/main/BubbleSort.java @@ -0,0 +1,33 @@ +import java.util.Arrays; + +/** + * 冒泡排序 + */ +public class BubbleSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + for (int i = 1; i < arr.length; i++) { + // 设定一个标记,若为true,则表示此次循环没有进行交换,也就是待排序列已经有序,排序已经完成。 + boolean flag = true; + + for (int j = 0; j < arr.length - i; j++) { + if (arr[j] > arr[j + 1]) { + int tmp = arr[j]; + arr[j] = arr[j + 1]; + arr[j + 1] = tmp; + + flag = false; + } + } + + if (flag) { + break; + } + } + return arr; + } +} diff --git a/src/java/main/BucketSort.java b/src/java/main/BucketSort.java new file mode 100644 index 0000000..c0b5183 --- /dev/null +++ b/src/java/main/BucketSort.java @@ -0,0 +1,69 @@ +import java.util.Arrays; + +/** + * 桶排序 + */ +public class BucketSort implements IArraySort { + + private static final InsertSort insertSort = new InsertSort(); + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + return bucketSort(arr, 5); + } + + private int[] bucketSort(int[] arr, int bucketSize) throws Exception { + if (arr.length == 0) { + return arr; + } + + int minValue = arr[0]; + int maxValue = arr[0]; + for (int value : arr) { + if (value < minValue) { + minValue = value; + } else if (value > maxValue) { + maxValue = value; + } + } + + int bucketCount = (int) Math.floor((maxValue - minValue) / bucketSize) + 1; + int[][] buckets = new int[bucketCount][0]; + + // 利用映射函数将数据分配到各个桶中 + for (int i = 0; i < arr.length; i++) { + int index = (int) Math.floor((arr[i] - minValue) / bucketSize); + buckets[index] = arrAppend(buckets[index], arr[i]); + } + + int arrIndex = 0; + for (int[] bucket : buckets) { + if (bucket.length <= 0) { + continue; + } + // 对每个桶进行排序,这里使用了插入排序 + bucket = insertSort.sort(bucket); + for (int value : bucket) { + arr[arrIndex++] = value; + } + } + + return arr; + } + + /** + * 自动扩容,并保存数据 + * + * @param arr + * @param value + */ + private int[] arrAppend(int[] arr, int value) { + arr = Arrays.copyOf(arr, arr.length + 1); + arr[arr.length - 1] = value; + return arr; + } + +} diff --git a/src/java/main/CountingSort.java b/src/java/main/CountingSort.java new file mode 100644 index 0000000..74fcd2a --- /dev/null +++ b/src/java/main/CountingSort.java @@ -0,0 +1,46 @@ +import java.util.Arrays; + +/** + * 计数排序 + */ +public class CountingSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int maxValue = getMaxValue(arr); + + return countingSort(arr, maxValue); + } + + private int[] countingSort(int[] arr, int maxValue) { + int bucketLen = maxValue + 1; + int[] bucket = new int[bucketLen]; + + for (int value : arr) { + bucket[value]++; + } + + int sortedIndex = 0; + for (int j = 0; j < bucketLen; j++) { + while (bucket[j] > 0) { + arr[sortedIndex++] = j; + bucket[j]--; + } + } + return arr; + } + + private int getMaxValue(int[] arr) { + int maxValue = arr[0]; + for (int value : arr) { + if (maxValue < value) { + maxValue = value; + } + } + return maxValue; + } + +} diff --git a/src/java/main/HeapSort.java b/src/java/main/HeapSort.java new file mode 100644 index 0000000..6e9dcfe --- /dev/null +++ b/src/java/main/HeapSort.java @@ -0,0 +1,56 @@ +import java.util.Arrays; + +/** + * 堆排序 + */ +public class HeapSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + int len = arr.length; + + buildMaxHeap(arr, len); + + for (int i = len - 1; i > 0; i--) { + swap(arr, 0, i); + len--; + heapify(arr, 0, len); + } + return arr; + } + + private void buildMaxHeap(int[] arr, int len) { + for (int i = (int) Math.floor(len / 2); i >= 0; i--) { + heapify(arr, i, len); + } + } + + private void heapify(int[] arr, int i, int len) { + int left = 2 * i + 1; + int right = 2 * i + 2; + int largest = i; + + if (left < len && arr[left] > arr[largest]) { + largest = left; + } + + if (right < len && arr[right] > arr[largest]) { + largest = right; + } + + if (largest != i) { + swap(arr, i, largest); + heapify(arr, largest, len); + } + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} diff --git a/src/java/main/IArraySort.java b/src/java/main/IArraySort.java new file mode 100644 index 0000000..7d607e5 --- /dev/null +++ b/src/java/main/IArraySort.java @@ -0,0 +1,14 @@ +/** + * Created by corning on 2017/12/19. + */ +public interface IArraySort { + /** + * 对数组进行排序,并返回排序后的数组 + * + * @param sourceArray + * @return + * @throws Exception + */ + int[] sort(int[] sourceArray) throws Exception; + +} diff --git a/src/java/main/InsertSort.java b/src/java/main/InsertSort.java new file mode 100644 index 0000000..1321972 --- /dev/null +++ b/src/java/main/InsertSort.java @@ -0,0 +1,34 @@ +import java.util.Arrays; + +/** + * 插入排序 + */ +public class InsertSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + // 从下标为1的元素开始选择合适的位置插入,因为下标为0的只有一个元素,默认是有序的 + for (int i = 1; i < arr.length; i++) { + + // 记录要插入的数据 + int tmp = arr[i]; + + // 从已经排序的序列最右边的开始比较,找到比其小的数 + int j = i; + while (j > 0 && tmp < arr[j - 1]) { + arr[j] = arr[j - 1]; + j--; + } + + // 存在比其小的数,插入 + if (j != i) { + arr[j] = tmp; + } + + } + return arr; + } +} diff --git a/src/java/main/MergeSort.java b/src/java/main/MergeSort.java new file mode 100644 index 0000000..7fec2b8 --- /dev/null +++ b/src/java/main/MergeSort.java @@ -0,0 +1,50 @@ +import java.util.Arrays; + +/** + * 归并排序 + */ +public class MergeSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + if (arr.length < 2) { + return arr; + } + int middle = (int) Math.floor(arr.length / 2); + + int[] left = Arrays.copyOfRange(arr, 0, middle); + int[] right = Arrays.copyOfRange(arr, middle, arr.length); + + return merge(sort(left), sort(right)); + } + + protected int[] merge(int[] left, int[] right) { + int[] result = new int[left.length + right.length]; + int i = 0; + while (left.length > 0 && right.length > 0) { + if (left[0] <= right[0]) { + result[i++] = left[0]; + left = Arrays.copyOfRange(left, 1, left.length); + } else { + result[i++] = right[0]; + right = Arrays.copyOfRange(right, 1, right.length); + } + } + + while (left.length > 0) { + result[i++] = left[0]; + left = Arrays.copyOfRange(left, 1, left.length); + } + + while (right.length > 0) { + result[i++] = right[0]; + right = Arrays.copyOfRange(right, 1, right.length); + } + + return result; + } + +} diff --git a/src/java/main/QuickSort.java b/src/java/main/QuickSort.java new file mode 100644 index 0000000..1c598ed --- /dev/null +++ b/src/java/main/QuickSort.java @@ -0,0 +1,45 @@ +import java.util.Arrays; + +/** + * 快速排序 + */ +public class QuickSort implements IArraySort { + + @Override + public int[] sort(int[] sourceArray) throws Exception { + // 对 arr 进行拷贝,不改变参数内容 + int[] arr = Arrays.copyOf(sourceArray, sourceArray.length); + + return quickSort(arr, 0, arr.length - 1); + } + + private int[] quickSort(int[] arr, int left, int right) { + if (left < right) { + int partitionIndex = partition(arr, left, right); + quickSort(arr, left, partitionIndex - 1); + quickSort(arr, partitionIndex + 1, right); + } + return arr; + } + + private int partition(int[] arr, int left, int right) { + // 设定基准值(pivot) + int pivot = left; + int index = pivot + 1; + for (int i = index; i <= right; i++) { + if (arr[i] < arr[pivot]) { + swap(arr, i, index); + index++; + } + } + swap(arr, pivot, index - 1); + return index - 1; + } + + private void swap(int[] arr, int i, int j) { + int temp = arr[i]; + arr[i] = arr[j]; + arr[j] = temp; + } + +} diff --git a/src/java/main/RadixSort.java b/src/java/main/RadixSort.java new file mode 100644 index 0000000..9052e76 --- /dev/null +++ b/src/java/main/RadixSort.java @@ -0,0 +1,83 @@ +import java.util.Arrays; + +/** + * 基数排序 + *
+ * 考虑负数的情况还可以参考: https://code.i-harness.com/zh-CN/q/e98fa9
+ */
+public class RadixSort implements IArraySort {
+
+ @Override
+ public int[] sort(int[] sourceArray) throws Exception {
+ // 对 arr 进行拷贝,不改变参数内容
+ int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
+
+ int maxDigit = getMaxDigit(arr);
+ return radixSort(arr, maxDigit);
+ }
+
+ /**
+ * 获取最高位数
+ */
+ private int getMaxDigit(int[] arr) {
+ int maxValue = getMaxValue(arr);
+ return getNumLenght(maxValue);
+ }
+
+ private int getMaxValue(int[] arr) {
+ int maxValue = arr[0];
+ for (int value : arr) {
+ if (maxValue < value) {
+ maxValue = value;
+ }
+ }
+ return maxValue;
+ }
+
+ protected int getNumLenght(long num) {
+ if (num == 0) {
+ return 1;
+ }
+ int lenght = 0;
+ for (long temp = num; temp != 0; temp /= 10) {
+ lenght++;
+ }
+ return lenght;
+ }
+
+ private int[] radixSort(int[] arr, int maxDigit) {
+ int mod = 10;
+ int dev = 1;
+
+ for (int i = 0; i < maxDigit; i++, dev *= 10, mod *= 10) {
+ // 考虑负数的情况,这里扩展一倍队列数,其中 [0-9]对应负数,[10-19]对应正数 (bucket + 10)
+ int[][] counter = new int[mod * 2][0];
+
+ for (int j = 0; j < arr.length; j++) {
+ int bucket = ((arr[j] % mod) / dev) + mod;
+ counter[bucket] = arrayAppend(counter[bucket], arr[j]);
+ }
+
+ int pos = 0;
+ for (int[] bucket : counter) {
+ for (int value : bucket) {
+ arr[pos++] = value;
+ }
+ }
+ }
+
+ return arr;
+ }
+
+ /**
+ * 自动扩容,并保存数据
+ *
+ * @param arr
+ * @param value
+ */
+ private int[] arrayAppend(int[] arr, int value) {
+ arr = Arrays.copyOf(arr, arr.length + 1);
+ arr[arr.length - 1] = value;
+ return arr;
+ }
+}
diff --git a/src/java/main/SelectionSort.java b/src/java/main/SelectionSort.java
new file mode 100644
index 0000000..0cee685
--- /dev/null
+++ b/src/java/main/SelectionSort.java
@@ -0,0 +1,34 @@
+import java.util.Arrays;
+
+/**
+ * 选择排序
+ */
+public class SelectionSort implements IArraySort {
+
+ @Override
+ public int[] sort(int[] sourceArray) throws Exception {
+ int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
+
+ // 总共要经过 N-1 轮比较
+ for (int i = 0; i < arr.length - 1; i++) {
+ int min = i;
+
+ // 每轮需要比较的次数 N-i
+ for (int j = i + 1; j < arr.length; j++) {
+ if (arr[j] < arr[min]) {
+ // 记录目前能找到的最小值元素的下标
+ min = j;
+ }
+ }
+
+ // 将找到的最小值和i位置所在的值进行交换
+ if (i != min) {
+ int tmp = arr[i];
+ arr[i] = arr[min];
+ arr[min] = tmp;
+ }
+
+ }
+ return arr;
+ }
+}
diff --git a/src/java/main/ShellSort.java b/src/java/main/ShellSort.java
new file mode 100644
index 0000000..6c0fbb1
--- /dev/null
+++ b/src/java/main/ShellSort.java
@@ -0,0 +1,33 @@
+import java.util.Arrays;
+
+/**
+ * 希尔排序
+ */
+public class ShellSort implements IArraySort {
+
+ @Override
+ public int[] sort(int[] sourceArray) throws Exception {
+ // 对 arr 进行拷贝,不改变参数内容
+ int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
+
+ int gap = 1;
+ while (gap < arr.length) {
+ gap = gap * 3 + 1;
+ }
+
+ while (gap > 0) {
+ for (int i = gap; i < arr.length; i++) {
+ int tmp = arr[i];
+ int j = i - gap;
+ while (j >= 0 && arr[j] > tmp) {
+ arr[j + gap] = arr[j];
+ j -= gap;
+ }
+ arr[j + gap] = tmp;
+ }
+ gap = (int) Math.floor(gap / 3);
+ }
+
+ return arr;
+ }
+}
diff --git a/src/java/pom.xml b/src/java/pom.xml
new file mode 100644
index 0000000..60b4858
--- /dev/null
+++ b/src/java/pom.xml
@@ -0,0 +1,70 @@
+
+