目录
准备工作
排序规则
按照自然序排序(从左往右,从小到大)
工具类
public class SortUtil {
/**
* 交换 arr[a] 与 arr[b]
* @param arr 数组
* @param a index a
* @param b index b
*/
public static void swap(int[] arr, int a, int b) {
int temp = arr[a];
arr[a] = arr[b];
arr[b] = temp;
}
}
测试类
public class EightSortMethod {
public static void main(String[] args) {
int[] arr;
// 1. 冒泡排序(Bubble Sort): 通过相邻元素的比较和交换来将较大的元素逐渐从后面移动到数组的末尾,较小的元素逐渐从前面移动到数组的开头。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(BubbleSort.sort(arr)));
// 2. 选择排序(Selection Sort): 每次从未排序的部分选择最小(或最大)的元素,然后将其与未排序部分的第一个元素交换,直到所有元素排序完成。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(SelectionSort.sort(arr)));
// 3. 插入排序(Insertion Sort): 将数组分成已排序和未排序两部分,每次从未排序部分取出一个元素插入到已排序部分的适当位置,直到所有元素都插入完毕。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(InsertionSort.sort(arr)));
// 4. 希尔排序(Shell Sort): 是插入排序的一种改进版本,它通过将数组分成多个子序列来排序,每个子序列使用插入排序进行排序,不断缩小子序列的间隔直到为1。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(ShellSort.sort(arr)));
// 5. 归并排序(Merge Sort): 采用分治法的思想,将数组递归地分成两个子数组,然后将两个有序子数组合并为一个有序数组,直到整个数组有序。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(MergeSort.sort(arr)));
// 6. 快速排序(Quick Sort): 也是采用分治法的思想,通过选取一个基准元素,将数组分成两个子数组,左边的子数组小于等于基准元素,右边的子数组大于基准元素,然后递归地对两个子数组进行排序。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(QuickSort.sort(arr)));
// 7. 堆排序(Heap Sort): 利用堆这种数据结构来实现的一种排序算法,通过构建最大堆(或最小堆)来实现排序。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(HeapSort.sort(arr)));
// 8. 计数排序(Counting Sort): 非比较排序算法,适用于一定范围内的整数排序,它通过统计每个元素的个数来实现排序。
arr = new int[]{1, 5, 8, 2, 6, 0, 16, 88, 29, 91, 777};
System.out.println(Arrays.toString(CountingSort.sort(arr)));
}
}
1. 冒泡排序(Bubble Sort)
通过相邻元素的比较和交换来将较大的元素逐渐从后面移动到数组的末尾,较小的元素逐渐从前面移动到数组的开头。
public class BubbleSort {
public static int[] sort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n-1; i++) {
for (int j = 0; j < n - 1 - i; j++) {
if (arr[j] > arr[j + 1]) SortUtil.swap(arr, j, j + 1);
}
}
return arr;
}
}
2. 选择排序(Selection Sort)
每次从未排序的部分选择最小(或最大)的元素,然后将其与未排序部分的第一个元素交换,直到所有元素排序完成。
public class SelectionSort {
public static int[] sort(int[] arr) {
int n = arr.length;
for (int i = 0; i < n; i++) {
int minIndex = i;
for (int j = i + 1; j < n; j++) {
if (arr[j] < arr[minIndex]) minIndex = j;
}
SortUtil.swap(arr, i, minIndex);
}
return arr;
}
}
3. 插入排序(Insertion Sort)
将数组分成已排序和未排序两部分,每次从未排序部分取出一个元素插入到已排序部分的适当位置,直到所有元素都插入完毕。
public class InsertionSort {
public static int[] sort(int[] arr) {
int n = arr.length;
for (int i = 1; i < n; i++) {
int x = arr[i];
int end = i-1;
while (end >= 0 && arr[end] > x) {
arr[end + 1] = arr[end];
end--;
}
arr[end+1] = x;
}
return arr;
}
}
4. 希尔排序(Shell Sort)
是插入排序的一种改进版本,它通过将数组分成多个子序列来排序,每个子序列使用插入排序进行排序,不断缩小子序列的间隔直到为1。
public class ShellSort {
public static int[] sort(int[] arr) {
int n = arr.length;
for (int gap = n / 2; gap > 0; gap /= 2) {
for (int i = gap; i < n; i++) {
int x = arr[i];
int end = i - gap;
while (end >= 0 && arr[end] > x) {
arr[end + gap] = arr[end];
end -= gap;
}
arr[end + gap] = x;
}
}
return arr;
}
}
5. 归并排序(Merge Sort)
采用分治法的思想,将数组递归地分成两个子数组,然后将两个有序子数组合并为一个有序数组,直到整个数组有序。
public class MergeSort {
public static int[] sort(int[] arr) {
mergeSort(arr, 0, arr.length - 1);
return arr;
}
private static void mergeSort(int[] arr, int l, int r) {
if (l >= r) return;
int m = l + (r - l) / 2;
mergeSort(arr, l, m);
mergeSort(arr, m + 1, r);
merge(arr, l, m, r);
}
private static void merge(int[] arr, int l, int m, int r) {
int leftLen = m - l + 1;
int rightLen = r - m;
int[] left = new int[leftLen];
int[] right = new int[rightLen];
for (int i = 0; i < leftLen; i++) left[i] = arr[l + i];
for (int i = 0; i < rightLen; i++) right[i] = arr[m + 1 + i];
int lIndex = 0, rIndex = 0, mergeIndex = l;
while (lIndex < leftLen && rIndex < rightLen) {
arr[mergeIndex++] = left[lIndex] < right[rIndex] ? left[lIndex++] : right[rIndex++];
}
while (lIndex < leftLen) {
arr[mergeIndex++] = left[lIndex++];
}
while (rIndex < rightLen) {
arr[mergeIndex++] = right[rIndex++];
}
}
}
6. 快速排序(Quick Sort)
也是采用分治法的思想,通过选取一个基准元素,将数组分成两个子数组,左边的子数组小于等于基准元素,右边的子数组大于基准元素,然后递归地对两个子数组进行排序。
public class QuickSort {
public static int[] sort(int[] arr) {
quickSort(arr, 0, arr.length - 1);
return arr;
}
private static void quickSort(int[] arr, int l, int r) {
if (l >= r) return;
int pivot = partition(arr, l, r);
quickSort(arr, l, pivot - 1);
quickSort(arr, pivot + 1, r);
}
private static int partition(int[] arr, int l, int r) {
int pivot = l;
while (l < r) {
while (l < r && arr[r] >= arr[pivot]) r--;
while (l < r && arr[l] <= arr[pivot]) l++;
SortUtil.swap(arr, l, r);
}
SortUtil.swap(arr, l, pivot);
return l;
}
}
7. 堆排序(Heap Sort)
利用堆这种数据结构来实现的一种排序算法,通过构建最大堆(或最小堆)来实现排序。
public class HeapSort {
public static int[] sort(int[] arr) {
int n = arr.length;
// 建立大根堆
for (int i = n / 2 - 1; i >= 0; i--) heapify(arr, n, i);
// 删除法调整成小根堆
for (int i = n - 1; i > 0; i--) {
SortUtil.swap(arr, i, 0);
// 注意第二个参数是 i 不是 n
heapify(arr, i, 0);
}
return arr;
}
private static void heapify(int[] arr, int n, int i) {
int largest = i;
int left = 2 * i + 1;
int right = 2 * i + 2;
if (left < n && arr[left] > arr[largest]) largest = left;
if (right < n && arr[right] > arr[largest]) largest = right;
if (largest != i) {
SortUtil.swap(arr, i, largest);
heapify(arr, n, largest);
}
}
}
8. 计数排序(Counting Sort)
非比较排序算法,适用于一定范围内的整数排序,它通过统计每个元素的个数来实现排序。
public class CountingSort {
public static int[] sort(int[] arr) {
int max = Arrays.stream(arr).max().getAsInt();
int min = Arrays.stream(arr).min().getAsInt();
int range = max - min + 1;
int[] count = new int[range];
for (int i : arr) count[i - min]++;
int j = 0;
for (int i = 0; i < range; i++) {
while (count[i]-- > 0) arr[j++] = i + min;
}
return arr;
}
}
9. 桶排序(Bucket Sort)
计数排序的改进
public class BucketSort {
public static int[] sort(int[] arr) {
// Step 1: 确定桶的数量和范围
int maxValue = Arrays.stream(arr).max().getAsInt();
int minValue = Arrays.stream(arr).min().getAsInt();
int range = (maxValue - minValue) / arr.length + 1; // 桶的范围
int bucketSize = (maxValue - minValue) / range + 1; // 桶的数量
// Step 2: 创建桶并分配元素
List<List<Integer>> buckets = new ArrayList<>();
for (int i = 0; i < bucketSize; i++) buckets.add(new ArrayList<>());
for (int num : arr) {
int bucketIndex = (num - minValue) / range;
buckets.get(bucketIndex).add(num);
}
// Step 3: 对每个桶中的元素进行排序(这里使用了Java内置的排序方法)
for (List<Integer> bucket : buckets) Collections.sort(bucket);
// Step 4: 合并各个桶中的元素
int index = 0;
for (List<Integer> bucket : buckets) {
for (int num : bucket) {
arr[index++] = num;
}
}
return arr;
}
}