温故而知新,可以为师矣
重新过一下已经掌握的排序方法,最基础的东西往往最关键!
写在最前面
新年伊始就得了场感冒,咳嗽从19年咳到了20年,考完研也休息的差不多了,大家一起共勉!
文章框架
快速排序
package com.immunize.December.sort;
/**
* 快速排序1.2
*
* @author Mr IMMUNIZE
*
*/
public class Quick3 {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
quickSort(a, 0, a.length - 1);
// SimpleSelectSort2(a);
Print(a);
}
public static void quickSort(int[] a, int left, int right) {
int q;
if (left < right) {
q = Partition(a, left, right);
quickSort(a, left, q - 1);
quickSort(a, q + 1, right);
}
}
private static int Partition(int[] a, int left, int right) {
int i, j, s;
s = a[right];
i = left - 1;
for (j = left; j < right; j++) {
if (a[j] <= a[right]) {
i++;
Swap(a, i, j);
}
}
Swap(a, i + 1, right);
return i + 1;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
上面这个版本是最优的改进版本,因为快速排序的精髓在与找到最优的标准,以下附上以数组中间值作为标准来进行比较的快排代码:
package com.immunize.December.sort;
/**
* 快速排序1.1
*
* @author Mr IMMUNIZE
*
*/
public class Quick2 {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
QuickSort(a, 0, a.length - 1);
// SimpleSelectSort2(a);
Print(a);
}
/*
* 6 2 5 4 8 9 4 2 5 6 8 9 2 4 5 6 8 9
*
*/
public static void QuickSort(int[] a, int left, int right) {
int i, j, crit;
if (left > right)
return;
i = left - 1;
j = right + 1;
// crit = a[0];
crit = a[(left + right) / 2];
while (true) {
while (a[++i] < crit)
;
while (a[--j] > crit)
;
if (i >= j)
break;
Swap(a, i, j);
}
QuickSort(a, left, i - 1);
QuickSort(a, j + 1, right);
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
快速排序的最差时间复杂度为O(n²),但在大多数时候的效率是很好的,必须掌握。以下排序仅附上代码重写,不再赘述原理
堆排序
package com.immunize.December.sort;
/**
* Heap排序:基于选择排序的改进
*
* @author Mr IMMUNIZE
*
*/
public class Heap {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
HeapSort(a);
// SimpleSelectSort2(a);
Print(a);
}
// 堆排序
public static void HeapSort(int[] arr) {
// 构造大根堆
HeapInsert(arr);
int size = arr.length;
while (size > 1) {
// 交换大根和最后一个值,即固定最大值
Swap(arr, 0, size - 1);
// size递减
size--;
Heapify(arr, 0, size);
}
}
// 构造大根堆(通过新插入的数上升)
public static void HeapInsert(int[] arr) {
// 定义所使用的变量
int i, curIndex, faIndex;
for (i = 0; i < arr.length; i++) {
// 确定当前索引值
curIndex = i;
// 计算父节点索引值
faIndex = (curIndex - 1) / 2;
// 遍历,构造大根堆
while (arr[curIndex] > arr[faIndex]) {
Swap(arr, curIndex, faIndex);
// 将当前索引和父节点索引归位
curIndex = faIndex;
faIndex = (curIndex - 1) / 2;
}
}
}
// 将剩余的数构造成大根堆(通过顶端的数下降)
public static void Heapify(int[] arr, int index, int size) {
// 定义使用的变量
int left, right, largerIndex;
// 计算当前节点的左右节点索引
left = 2 * index + 1;
right = 2 * index + 2;
// 确保较小的子节点:左节点小于待排序节点个数
while (left < size) {
// 找到左右节点中较大的节点索引
if (arr[left] < arr[right] && right < size)
largerIndex = right;
else
largerIndex = left;
// 比较当前索引和左右节点中较大的索引处的值,若当前索引较大,则已经是大根堆,跳出循环即可。
if (arr[index] > arr[largerIndex]) {
largerIndex = index;
break;
}
Swap(arr, index, largerIndex);
// 重新指向当前索引和当前索引的左右子节点
index = largerIndex;
left = 2 * index + 1;
right = 2 * index + 2;
}
}
// 交换数组中两个元素的值
public static void Swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
}
希尔排序
package com.immunize.December.sort;
public class Shell {
public static void main(String[] args) {
// 生成原始数组
int[] a = Generate(100, 10);
// 原始数组打印
System.out.println("原始数组:");
Print(a);
// 希尔排序后的数组打印
System.out.println("排序后的数组");
// shellSort1(a);
shellSort2(a);
Print(a);
}
public static void shellSort2(int[] a) {
int gap = a.length / 2;
int i, j;
for (; gap > 0; gap /= 2) {
for (i = gap; i < a.length; i++) {
j = i;
while (j - gap >= 0 && a[j] < a[j - gap]) {
Swap(a, j, j - gap);
j -= gap;
}
}
}
}
// 希尔排序
public static void shellSort1(int[] arr) {
int i, j, k, tmp;
int gap = arr.length / 2;
while (gap > 0) {
for (k = 0; k < gap; k++) {
for (i = k + gap; i < arr.length; i += gap) {
for (j = i - gap; j >= k; j -= gap) {
if (arr[j] > arr[j + gap]) {
Swap(arr, j, j + gap);
} else {
break;
}
}
}
}
gap /= 2;
}
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
计数排序
package com.immunize.December.sort;
public class Count {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
Print(countSort(a));
}
public static int[] countSort(int[] a) {
// 找出数组中的最大值
int max = Integer.MIN_VALUE;
for (int num : a) {
max = Math.max(max, num);
}
// 初始化计数数组
int[] count = new int[max + 1];
// 对数组计数
for (int num : a) {
count[num]++;
}
// 创建结果数组
int[] result = new int[a.length];
int index = 0;
for (int i = 0; i < count.length; i++) {
while (count[i] > 0) {
result[index++] = i;
count[i]--;
}
}
return result;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
桶排序
package com.immunize.December.sort;
public class Radix {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
System.out.println("排序后的数组");
RadixSort(a, 3);
Print(a);
}
public static void RadixSort(int[] arr, int max) {
// count数组用来计数
int[] count = new int[arr.length];
// bucket用来当桶(在下面你就理解了什么是桶了),放数据,取数据
int[] bucket = new int[arr.length];
// k表示第几位,1代表个位,2代表十位,3代表百位
for (int k = 1; k <= max; k++) {
// 把count置空,防止上次循环的数据影响
for (int i = 0; i < arr.length; i++) {
count[i] = 0;
}
// 分别统计第k位是0,1,2,3,4,5,6,7,8,9的数量
// 以下便称为桶
// 即此循环用来统计每个桶中的数据的数量
for (int i = 0; i < arr.length; i++) {
count[getFigure(arr[i], k)]++;
}
// 利用count[i]来确定放置数据的位置
for (int i = 1; i < arr.length; i++) {
count[i] = count[i] + count[i - 1];
}
// 执行完此循环之后的count[i]就是第i个桶右边界的位置
// 利用循环把数据装入各个桶中,注意是从后往前装
// 这里是重点,一定要仔细理解
for (int i = arr.length - 1; i >= 0; i--) {
int j = getFigure(arr[i], k);
bucket[count[j] - 1] = arr[i];
count[j]--;
}
// 将桶中的数据取出来,赋值给arr
for (int i = 0, j = 0; i < arr.length; i++, j++) {
arr[i] = bucket[j];
}
}
}
// 此函数返回整型数i的第k位是什么
public static int getFigure(int i, int k) {
int[] a = { 1, 10, 100 };
return (i / a[k - 1]) % 10;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
冒泡排序
package com.immunize.December.sort;
public class Bubble {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
bubbleSort(a);
// SimpleSelectSort2(a);
Print(a);
}
public static void bubbleSort(int[] a) {
// 两两对比,每次将最大的放到最后面
int i, j;
// i为遍历指针,从0-a.length-2
for (i = 0; i < a.length - 1; i++) {
// j为比较指针,从1-(a.length-i)
for (j = 1; j < a.length - i; j++) {
if (a[j] < a[j - 1])
Swap(a, j, j - 1);
}
}
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
鸡尾酒排序
package com.immunize.December.sort;
import java.util.Arrays;
public class Shaker {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
ShakerSort(a);
// SimpleSelectSort2(a);
Print(a);
// Print(cocktailSort(a));
}
public static void ShakerSort(int[] a) {
int i, j, left, right, shift;
left = 0;
right = a.length - 1;
shift = 0;
while (left < right) {
for (i = left; i < right; i++) {
if (a[i] > a[i + 1]) {
Swap(a, i, i + 1);
shift = i;
}
}
right = shift;
for (j = right; j > left; j--) {
if (a[j - 1] > a[j]) {
Swap(a, j, j - 1);
shift = j;
}
}
left = shift;
}
}
public static int[] cocktailSort(int[] src) {
int len = src.length;
// 将最小值排到队尾
for (int i = 0; i < len / 2; i++) {
for (int j = i; j < len - i - 1; j++) {
if (src[j] < src[j + 1]) {
int temp = src[j];
src[j] = src[j + 1];
src[j + 1] = temp;
}
System.out.println("交换小" + Arrays.toString(src));
}
// 将最大值排到队头
for (int j = len - 1 - (i + 1); j > i; j--) {
if (src[j] > src[j - 1]) {
int temp = src[j];
src[j] = src[j - 1];
src[j - 1] = temp;
}
System.out.println("交换大" + Arrays.toString(src));
}
System.out.println("第" + i + "次排序结果:" + Arrays.toString(src));
}
return src;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
鸡尾酒排序这里多说一点,两种写法都在代码中呈现出来,ShakerSort/cocktailSort都称为鸡尾酒排序
选择排序
package com.immunize.December.sort;
import java.util.Arrays;
public class Select {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
// Print(Arrays.copyOfRange(a, 0, a.length));
System.out.println("排序后的数组");
// selectSort1(a);
selectSort2(a);
// SimpleSelectSort2(a);
Print(a);
}
public static void selectSort1(int[] a) {
int i, j, tmp;
for (i = 0; i < a.length - 1; i++) {
// 获取当前索引
tmp = i;
for (j = i + 1; j < a.length; j++) {
if (a[tmp] > a[j]) {
Swap(a, j, tmp);
}
}
}
}
public static void selectSort2(int[] a) {
int i, j, tmp;
for (i = 0; i < a.length - 1; i++) {
tmp = i;
Swap(a, tmp, FindMinIndex(Arrays.copyOfRange(a, i, a.length)) + i);
}
}
public static int FindMinIndex(int[] a) {
int i, min, minIndex = 0;
min = a[0];
for (i = 1; i < a.length; i++) {
if (a[i] < min) {
min = a[i];
minIndex = i;
}
}
return minIndex;
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
插入排序
package com.immunize.December.sort;
public class Insert {
public static void main(String[] args) {
// 生成一个随机的数组
int[] a = Generate(100, 10);
// 对这个数组进行打印
System.out.println("原始数组:");
Print(a);
System.out.println("排序后的数组");
insertSort(a);
// SimpleSelectSort2(a);
Print(a);
}
// 插入排序
public static void insertSort(int[] a) {
int i, j, tmp;
// 遍历
// i从1-末尾
for (i = 1; i < a.length; i++) {
// 当前值tmp
tmp = a[i];
// 前一个值的索引
j = i - 1;
// 当前值与每一个在其之前的数比较
while (tmp < a[j]) {
// 前值较大的话则需要往后移
a[j + 1] = a[j];
j--;
// 移动的上限是第一个值
if (j == -1) {
break;
}
}
// 跳出循环,当前值赋值到空出来的那个位置
a[j + 1] = tmp;
}
}
// Print函数
public static void Print(int[] arr) {
System.out.print("[");
for (int i = 0; i < arr.length; i++) {
if (i == arr.length - 1) {
System.out.print(arr[i]);
break;
}
System.out.print(arr[i] + ",");
}
System.out.print("]");
System.out.println();
}
// 随机生成n个数字,组成随机数组函数Generate函数
public static int[] Generate(int max, int length) {
int[] arr = new int[length];
for (int i = 0; i < length; i++) {
arr[i] = (int) (Math.random() * max);
}
return arr;
}
// Swap函数
public static void Swap(int[] arr, int i, int j) {
int tmp = 0;
tmp = arr[i];
arr[i] = arr[j];
arr[j] = tmp;
}
}
基数排序
package com.immunize.Arithmetic;
/**
* 基数排序法
*
* @author Mr IMMUNIZE
*
*/
public class RadixSort {
public static void main(String[] args) {
int[] data = { 73, 22, 93, 43, 55, 14, 28, 65, 39, 81 };
int[][] temp = new int[10][10];
int[] order = { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
int i, j, k, n, lsd;
k = 0;
n = 1;
System.out.println("排序前:");
Print(data);
System.out.println();
while (n <= 10) {
for (i = 0; i < 10; i++) {
// 拿到个位数数字
lsd = ((data[i] / n) % 10);
// 将该数据存放在对应的列上,21就放在第一列,89就放在第9列
temp[lsd][order[lsd]] = data[i];
// order[lsd]表示行数,行数递增
order[lsd]++;
}
for (i = 0; i < 10; i++) {
// 重新排列,先列后行
if (order[i] != 0) {
// 先列再行,每一行只有一个数据,每一列的数据按照行序排列
for (j = 0; j < order[i]; j++) {
data[k] = temp[i][j];
k++;
}
}
order[i] = 0;
}
n *= 10;
k = 0;
}
System.out.println("排序后:");
Print(data);
}
public static void Print(int[] number) {
for (int i = 0; i < number.length; i++) {
System.out.print(number[i] + " ");
}
}
}
基数排序代码未重写,是直接取自我之前20191015的博客。
结语
至此,十大排序除了归并排序其余的都已经附上重写代码,而归并排序实际上是Java中Arrays的sort方法的本质,我们明天给予说明。