前言
对数组中的整数排序是常见的算法, 其中简单排序是最基础的算法
一、思路
各排序算法见代码注释;无外乎 选定一个位置或指定数,按规则比较后交换
二、题解
选择排序
public class Code01_SelectionSort {
/**
* 选择排序 1-n-1 将比较后的最小值放在 0 位
* 2-n-1 将比较后的最小值放在 1 位
* 拿到每次完成循环中的最小值 和 arr[i] 交换; 查询最小值过程可以不交换, 知道最小值的索引即可
*
* @param arr
*/
private static void selectionSort(int[] arr) {
// 排除特殊情况
if (arr == null || arr.length < 2) {
return;
}
for (int i = 0; i < arr.length; i++) {
int minIndex = i;
for(int j= i+1;j<arr.length;j++) {
minIndex = arr[j] < arr[minIndex] ? j : minIndex;
}
// 将最小值交换到 minIndex位置上
swap(arr, i,minIndex);
}
}
/**
* 常规的 2 数交换
* @param arr
* @param i
* @param j
*/
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
/**
* 创建一个随机数的数组
*
* @param maxSize 数组最大容量
* @param maxValue 数组元素 最大值
* @return
*/
private static int[] generateRandomArray(int maxSize, int maxValue) {
// Math.random() [0 1)
// Math.random() * N [0, N)
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
// 每个元素赋值
for (int i = 0; i < arr.length; i++) {
//这种写法可以产生复数
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
//只能由正整数
//arr[i] = (int) ((maxValue + 1) * Math.random());
}
return arr;
}
/**
* 复制一个数组
* @param arr
*/
private static int[] copyArray(int[] arr) {
if(arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//打印数组中的元素
private static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
/**
* 比较器, 用 java 数组api排序
* @param arr
*/
private static void comparator(int[] arr) {
Arrays.sort(arr);
}
/**
* 比较2 数组是否相等
* @param arr1
* @param arr2
* @return
*/
private static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 != null && arr2 == null) || (arr1 == null && arr2 != null)) {
return false;
}
if(arr1 == null && arr2 == null) {
return true;
}
if(arr1.length != arr2.length) {
return false;
}
// 比较每个元素
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
/**
* 主程序
* @param args
*/
public static void main(String[] args) {
int maxSize = 100;
int maxValue = 100;
int maxTimes = 500000;
boolean success = true;
for (int i = 0; i < maxTimes; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
selectionSort(arr1);
comparator(arr2);
if(!isEqual(arr1, arr2)) {
success =false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success ? "Nice!":"Bad");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
selectionSort(arr);
printArray(arr);
}
}
冒泡排序
public class Code02_BubbleSort {
/**
* 冒泡排序
* 思路: 两两比较, 大的数交换到右侧
* 0 ~ n-1 比较 n-1 次 最大值在 arr[n-1] 上
* 0 ~ n-2 比较 n-2 次 最大值在 arr[n-2] 上
* @param arr
*/
private static void bubbleSort(int[] arr) {
// 排除特殊情况
if (arr == null || arr.length < 2) {
return;
}
for (int e = arr.length-1; e > 0; e--) {
for(int i = 0; i< e;i++) {
if(arr[i] > arr[i+1]) {
swap(arr, i, i+1);
}
}
}
}
/**
* 异或运算的 2 数交换
* 满足交换律和结合律
* 0 ^ N = N
* N ^ N = 0
* 是不进位的二进制加法运算
* 1001
* 1111
* ----
* 0110
* @param arr
* @param i
* @param j
*/
private static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
/**
* 创建一个随机数的数组
*
* @param maxSize 数组最大容量
* @param maxValue 数组元素 最大值
* @return
*/
private static int[] generateRandomArray(int maxSize, int maxValue) {
// Math.random() [0 1)
// Math.random() * N [0, N)
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
// 每个元素赋值
for (int i = 0; i < arr.length; i++) {
//这种写法可以产生复数
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
//只能由正整数
//arr[i] = (int) ((maxValue + 1) * Math.random());
}
return arr;
}
/**
* 复制一个数组
* @param arr
*/
private static int[] copyArray(int[] arr) {
if(arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//打印数组中的元素
private static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
/**
* 比较器, 用 java 数组api排序
* @param arr
*/
private static void comparator(int[] arr) {
Arrays.sort(arr);
}
/**
* 比较2 数组是否相等
* @param arr1
* @param arr2
* @return
*/
private static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 != null && arr2 == null) || (arr1 == null && arr2 != null)) {
return false;
}
if(arr1 == null && arr2 == null) {
return true;
}
if(arr1.length != arr2.length) {
return false;
}
// 比较每个元素
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
/**
* 主程序
* @param args
*/
public static void main(String[] args) {
int maxSize = 100;
int maxValue = 100;
int maxTimes = 500000;
boolean success = true;
for (int i = 0; i < maxTimes; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
bubbleSort(arr1);
comparator(arr2);
if(!isEqual(arr1, arr2)) {
success =false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success ? "Nice!":"Bad");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
bubbleSort(arr);
printArray(arr);
}
}
直接插入排序
public class Code03_InsertionSort {
/**
* 插入排序-直接插入
* 思路: 选定一个数, 从它左侧开始比较;有遇到比它大的数进行交换;
* 知道它左边是小的数, 右边是大的数, 有点类似于扑克牌插入合适的位置
* @param arr
*/
private static void insertionSort(int[] arr) {
// 排除特殊情况
if (arr == null || arr.length < 2) {
return;
}
for (int i = 1; i < arr.length; i++) {
// j 往左走; 如果左边碰到大的数需要交换; 碰到小的数直接跳出循环
for(int j = i-1; j>=0 && arr[j]> arr[j+1]; j--) {
swap(arr, j, j+1);
}
}
}
/**
* 异或运算的 2 数交换
* 满足交换律和结合律
* 0 ^ N = N
* N ^ N = 0
* 是不进位的二进制加法运算
* 1001
* 1111
* ----
* 0110
* @param arr
* @param i
* @param j
*/
private static void swap(int[] arr, int i, int j) {
arr[i] = arr[i] ^ arr[j];
arr[j] = arr[i] ^ arr[j];
arr[i] = arr[i] ^ arr[j];
}
/**
* 创建一个随机数的数组
*
* @param maxSize 数组最大容量
* @param maxValue 数组元素 最大值
* @return
*/
private static int[] generateRandomArray(int maxSize, int maxValue) {
// Math.random() [0 1)
// Math.random() * N [0, N)
int[] arr = new int[(int) (Math.random() * (maxSize + 1))];
// 每个元素赋值
for (int i = 0; i < arr.length; i++) {
//这种写法可以产生复数
arr[i] = (int) ((maxValue + 1) * Math.random()) - (int) (maxValue * Math.random());
//只能由正整数
//arr[i] = (int) ((maxValue + 1) * Math.random());
}
return arr;
}
/**
* 复制一个数组
* @param arr
*/
private static int[] copyArray(int[] arr) {
if(arr == null) {
return null;
}
int[] res = new int[arr.length];
for (int i = 0; i < arr.length; i++) {
res[i] = arr[i];
}
return res;
}
//打印数组中的元素
private static void printArray(int[] arr) {
if (arr == null) {
return;
}
for (int i = 0; i < arr.length; i++) {
System.out.print(arr[i] + " ");
}
System.out.println();
}
/**
* 比较器, 用 java 数组api排序
* @param arr
*/
private static void comparator(int[] arr) {
Arrays.sort(arr);
}
/**
* 比较2 数组是否相等
* @param arr1
* @param arr2
* @return
*/
private static boolean isEqual(int[] arr1, int[] arr2) {
if ((arr1 != null && arr2 == null) || (arr1 == null && arr2 != null)) {
return false;
}
if(arr1 == null && arr2 == null) {
return true;
}
if(arr1.length != arr2.length) {
return false;
}
// 比较每个元素
for (int i = 0; i < arr1.length; i++) {
if(arr1[i] != arr2[i]) {
return false;
}
}
return true;
}
/**
* 主程序
* @param args
*/
public static void main(String[] args) {
int maxSize = 100;
int maxValue = 100;
int maxTimes = 500000;
boolean success = true;
for (int i = 0; i < maxTimes; i++) {
int[] arr1 = generateRandomArray(maxSize, maxValue);
int[] arr2 = copyArray(arr1);
insertionSort(arr1);
comparator(arr2);
if(!isEqual(arr1, arr2)) {
success =false;
printArray(arr1);
printArray(arr2);
break;
}
}
System.out.println(success ? "Nice!":"Bad");
int[] arr = generateRandomArray(maxSize, maxValue);
printArray(arr);
insertionSort(arr);
printArray(arr);
}
}
总结
简单排序, 数组元素左右比较, 按规则交换