【Java】常见的排序算法
冒泡排序
private static void bubble(int[] a) {
int j = a.length - 1;
do {
int x = 0;
for (int i = 0; i < j; i++) {
if (a[i] > a[i + 1]) {
int t = a[i];
a[i] = a[i + 1];
a[i + 1] = t;
x = i;
}
}
j = x;
} while (j != 0);
}
选择排序
public static void sort(int[] a) {
// 1. 选择轮数 a.length - 1
// 2. 交换的索引位置(right) 初始 a.length - 1, 每次递减
for (int right = a.length - 1; right > 0 ; right--) {
int max = right;
for (int i = 0; i < right; i++) {
if (a[i] > a[max]) {
max = i;
}
}
if(max != right) {
int t = a[max];
a[max] = a[right];
a[right] = t;
}
}
}
插入排序
public static void sort(int[] a) {
for (int low = 1; low < a.length; low++) {
int t = a[low];
int i = low - 1;
// 自右向左找插入位置,如果比待插入元素大,则不断右移,空出插入位置
while (i >= 0 && t < a[i]) {
a[i + 1] = a[i];
i--;
}
// 找到插入位置
if (i != low - 1) {
a[i + 1] = t;
}
}
}
归并排序
public static void sort(int[] a) {
for (int low = 1; low < a.length; low++) {
int t = a[low];
int i = low - 1;
// 自右向左找插入位置,如果比待插入元素大,则不断右移,空出插入位置
while (i >= 0 && t < a[i]) {
a[i + 1] = a[i];
i--;
}
// 找到插入位置
if (i != low - 1) {
a[i + 1] = t;
}
}
}
public static void merge(int[] a1, int i, int iEnd, int j, int jEnd, int[] a2) {
int k = i;
while (i <= iEnd && j <= jEnd) {
if (a1[i] < a1[j]) {
a2[k] = a1[i];
i++;
} else {
a2[k] = a1[j];
j++;
}
k++;
}
if (i > iEnd) {
System.arraycopy(a1, j, a2, k, jEnd - j + 1);
}
if (j > jEnd) {
System.arraycopy(a1, i, a2, k, iEnd - i + 1);
}
}
快速排序
public static void sort(int[] a) {
quick(a, 0, a.length - 1);
}
private static void quick(int[] a, int left, int right) {
if (left >= right) {
return;
}
int p = partition(a, left, right);
quick(a, left, p - 1);
quick(a, p + 1, right);
}
/*
注意事项
1. 为啥要加内层循环的 i<j 条件
2. 为啥要先处理 j,再处理 i
3. 随机元素作为基准点
4. 如果有大量重复元素
*/
private static int partition(int[] a, int left, int right) {
int idx = ThreadLocalRandom.current().nextInt(right - left + 1) + left;
// [0~9] right-left+1=3 [0,2]+4=[4,6]
swap(a, idx, left);
int pv = a[left];
int i = left;
int j = right;
while (i < j) {
// 1. j 从右向左找小(等)的
while (i < j && a[j] > pv) {
j--;
}
// 2. i 从左向右找大的
while (i < j && a[i] <= pv) {
i++;
}
// 3. 交换位置
swap(a, i, j);
}
swap(a, left, i);
return i;
}
private static void swap(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
堆排序 (建堆,循环下潜)
public static void sort(int[] a) {
heapify(a, a.length);
for (int right = a.length - 1; right > 0; right--) {
swap(a, 0, right);
down(a, 0, right);
}
}
// 建堆 O(n)
private static void heapify(int[] array, int size) {
for (int i = size / 2 - 1; i >= 0; i--) {
down(array, i, size);
}
}
// 下潜
// leetcode 上数组排序题目用堆排序求解,非递归实现比递归实现大约快 6ms
private static void down(int[] array, int parent, int size) {
while (true) {
int left = parent * 2 + 1;
int right = left + 1;
int max = parent;
if (left < size && array[left] > array[max]) {
max = left;
}
if (right < size && array[right] > array[max]) {
max = right;
}
if (max == parent) { // 没找到更大的孩子
break;
}
swap(array, max, parent);
parent = max;
}
}
// 交换
private static void swap(int[] a, int i, int j) {
int t = a[i];
a[i] = a[j];
a[j] = t;
}
计数排序算法
public static void sort(int[] a) {
// 1.循环数组获取最大值和最小值
int max = a[0];
int min = a[0];
for (int i = 1; i < a.length; i++) {
if (a[i] > max) {
max = a[i];
}
if (a[i] < min) {
min = a[i];
}
}
// 2. 每个数组表示一个整数,每个元素进行计数
int[] count = new int[max - min + 1];
for (int v : a) { // v 原始数组元素 - 最小值 = count 索引
count[v - min]++;
}
System.out.println(Arrays.toString(count));
// 将计数完成的值,转换为排序好的数组
int k = 0;
for (int i = 0; i < count.length; i++) {
// i + min 代表原始数组元素 count[i] 元素出现次数
while (count[i] > 0) {
a[k++] = i + min;
count[i]--;
}
}
}
桶排序算法
public static void sort(int[] ages) {
// 1. 准备桶
DynamicArray[] buckets = new DynamicArray[10];
for (int i = 0; i < buckets.length; i++) {
buckets[i] = new DynamicArray();
}
// 2. 放入年龄数据
for (int age : ages) {
buckets[age / 10].addLast(age);
}
int k = 0;
int j = 0;
for (DynamicArray bucket : buckets) {
// 3. 排序桶内元素
int[] array = bucket.array();
InsertionSort.sort(array);
System.out.println("桶[j]=>[" + j + "] " + Arrays.toString(array));
// 4. 把每个桶排序好的内容,依次放入原始数组
for (int v : array) {
ages[k++] = v;
}
j++;
}
}
基数排序算法
public static void radixSort(String[] a, int length) {
// 1. 准备桶
ArrayList<String>[] buckets = new ArrayList[128];
for (int i = 0; i < buckets.length; i++) {
buckets[i] = new ArrayList<>();
}
// 2. 进行多轮按位桶排序
for (int i = length - 1; i >= 0; i--) {
// 将字符串放入合适的桶
for (String s : a) {
buckets[s.charAt(i)].add(s);
}
// 重新取出排好序的字符串,放回原始数组
int k = 0;
for (ArrayList<String> bucket : buckets) {
for (String s : bucket) {
a[k++] = s;
}
bucket.clear();
}
// System.out.println(Arrays.toString(a));
}
}
有志者,事竟成,破釜沉舟,百二秦关终属楚; 苦心人,天不负,卧薪尝胆,三千越甲可吞吴。

浙公网安备 33010602011771号