最近温习了一下之前学的七七八八的常见排序算法
快速排序
// 快速排序 时间复杂度O(nlogn) 稳定性:不稳定
public static int[] quickSort(int[] nums, int start, int end) {
if (start < end) {
int i = start;
int j = end;
int temp = nums[start]; // 基准值 (优化点 可先取mid位子处的元素和start位子互换再开始快排)
while (i < j) {
while (i < j && nums[j] > temp) {
j--;
}
if (i < j)
nums[i++] = nums[j];
while (i < j && nums[i] < temp) {
i++;
}
if (i < j) {
nums[j--] = nums[i];
}
}
nums[i] = temp;
quickSort(nums, start, i - 1);
quickSort(nums, i + 1, end);
}
return nums;
}
归并排序
// 归并排序 时间复杂度O(nlogn) 稳定性: 稳定
public static void mergeSort(int[] nums, int i, int j) {
if (i < j) {
int mid = i + ((j - i) >> 1);
mergeSort(nums, i, mid);
mergeSort(nums, mid + 1, j);
merge(nums, i, mid, j);
}
}
private static void merge(int[] nums, int i, int mid, int j) {
int[] arr = new int[j - i + 1];
int x = i;
int y = mid + 1;
for (int a = 0; a < arr.length; a++) {
if (x > mid) {
arr[a] = nums[y++];
} else if (y > j) {
arr[a] = nums[x++];
} else if (nums[x] <= nums[y]) {
arr[a] = nums[x++];
} else
arr[a] = nums[y++];
}
for (int b = 0; b < arr.length; b++) {
nums[i + b] = arr[b];
}
}
插入排序
// 插入排序 时间复杂度 O(n^2) 稳定性:稳定
public static void insertSort(int[] nums) {
// 思路是 在已有序 序列基础上 继续添加元素 // 即在第一个元素后 遍历要添加的元素
// 从右到左依次比较有序序列 将要添加的元素插入合适的位子
for (int i = 1; i < nums.length; i++) {
int target = nums[i];
int pre = i - 1;
while (pre >= 0 && nums[pre] > target) {
nums[pre + 1] = nums[pre];
pre--;
}
nums[pre + 1] = target;
}
}
希尔排序
// 希尔排序是对插入排序的更高效的优化 插入排序即为gap为1的特殊场景 时间复杂度 O(nlog^2 n) 稳定性不稳定
//由于多次插入排序,我们知道一次插入排序是稳定的,不会改变相同元 素的相对顺序,
// 但在不同的插入排序过程中,相同的元素可能在各自的插入排序中移动,最后其稳定性就会被打乱;
public static void shellSort(int[] nums) {
int length = nums.length;
for (int gap = length >> 1; gap > 0; gap = gap >> 1) {
for (int i = gap; i < length; i++) {
insertSortByGap(nums, gap, i);
}
}
}
private static void insertSortByGap(int[] nums, int gap, int i) {
int current = nums[i];
int pre = i - gap;
while (pre >= 0 && nums[pre] > current) {
nums[pre + gap] = nums[pre];
pre -= gap;
}
nums[pre + gap] = current;
}
堆排序
// 借助优先队列 (堆)进行排序 时间复杂度O(nlogn) 稳定性 不稳定
public static void heapSort(int[] nums) {
PriorityQueue queue = new PriorityQueue<>(nums.length);
for (int i = 0; i < nums.length; i++) {
queue.offer(nums[i]);
}
for (int i = 0; i < nums.length; i++) {
nums[i] = queue.poll();
}
}
位图排序
// 位图排序 利用底层1字节8个bit位 来进行0,1设置
// 使用场景为:内存限制较大,数据不重复,知道数组中的最大值
public static int[] bitSort(int[] nums, int max) {
BitSet bitSet = new BitSet(max + 1);
for (int i = 0; i < nums.length; i++) {
bitSet.set(nums[i]);
}
return bitSet.stream().toArray();
}
冒泡排序
// 冒泡排序 时间复杂度度O(n^2) 稳定性:稳定
public static void bubbleSort(int[] nums) {
for (int i = nums.length - 1; i > 0; i--) {
boolean isSwap = true;
for (int j = 0; j < i; j++) {
if (nums[j] > nums[j + 1]) {
swap(nums, j, j + 1);
}
isSwap = false;
}
if (isSwap)
break;
}
}
选择排序
// 选择排序 时间复杂度度O(n^2) 稳定性:不稳定
public static void selectSort(int[] nums) {
for (int i = nums.length - 1; i > 0; i--) {
int maxIndex = i;
for (int j = 0; j < i; j++) {
if (nums[j] > nums[maxIndex]) {
maxIndex = j;
}
}
if (i != maxIndex)
swap(nums, i, maxIndex);
}
}
计数排序
// 计数排序 时间复杂度: 当输入的元素是 n 个 0到 k 之间的整数时,时间复杂度是O(n+k)
public static void countingSort(int[] nums, int max) {
int[] counting = new int[max + 1];
for (int i = 0; i < nums.length; i++) {
counting[nums[i]] += 1;
}
int x = 0;
for (int i = 0; i < counting.length; i++) {
if (counting[i] != 0) {
for (int j = 0; j < counting[i]; j++) {
nums[x++] = i;
}
}
}
}
private static void swap(int[] array, int x, int y) {
int temp = array[x];
array[x] = array[y];
array[y] = temp;
}