import java.util.Arrays;
public class 排序算法 {
public static void main(String[] args) throws Exception {
int[] nums = {1,4,3,2,5,8,6,7,9,10,12,11};
System.out.println(Arrays.toString(test1(nums))); //冒泡排序
System.out.println(Arrays.toString(test2(nums))); //选择排序
System.out.println(Arrays.toString(test3(nums))); //插入排序
System.out.println(Arrays.toString(test4(nums))); //希尔排序
System.out.println(Arrays.toString(test5(nums))); //并归排序
System.out.println(Arrays.toString(test6(nums))); //快速排序
System.out.println(Arrays.toString(test7(nums))); //堆排序
System.out.println(Arrays.toString(test8(nums))); //计数排序
System.out.println(Arrays.toString(test9(nums))); //桶排序
System.out.println(Arrays.toString(test10(nums))); //基数排序
}
//TODO 冒泡排序
public static int[] test1(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) {
for (int j = 0; j < len - 1 - i; j++) {
if (arr[j] > arr[j+1]) { // 相邻元素两两对比
int temp = arr[j+1]; // 元素交换
arr[j+1] = arr[j];
arr[j] = temp;
}
}
}
return arr;
}
//TODO 选择排序
public static int[] test2(int[] arr) {
int len = arr.length;
int minIndex, temp;
for (int i = 0; i < len - 1; i++) {
minIndex = i;
for (int j = i + 1; j < len; j++) {
if (arr[j] < arr[minIndex]) { // 寻找最小的数
minIndex = j; // 将最小数的索引保存
}
}
temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
return arr;
}
//TODO 插入排序
public static int[] test3(int[] arr) {
int len = arr.length;
int preIndex, current;
for (int i = 1; i < len; i++) {
preIndex = i - 1;
current = arr[i];
while(preIndex >= 0 && arr[preIndex] > current) {
arr[preIndex+1] = arr[preIndex];
preIndex--;
}
arr[preIndex+1] = current;
}
return arr;
}
//TODO 希尔排序
public static int[] test4(int[] arr) {
int length = arr.length;
int temp;
for (int step = length / 2; step >= 1; step /= 2) {
for (int i = step; i < length; i++) {
temp = arr[i];
int j = i - step;
while (j >= 0 && arr[j] > temp) {
arr[j + step] = arr[j];
j -= step;
}
arr[j + step] = temp;
}
}
return arr;
}
//TODO 并归排序
public static int[] test5(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
if (arr.length < 2) {
return arr;
}
int middle = (int) Math.floor(arr.length / 2);
int[] left = Arrays.copyOfRange(arr, 0, middle);
int[] right = Arrays.copyOfRange(arr, middle, arr.length);
return merge(test5(left), test5(right));
}
protected static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
int i = 0;
while (left.length > 0 && right.length > 0) {
if (left[0] <= right[0]) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
} else {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
}
while (left.length > 0) {
result[i++] = left[0];
left = Arrays.copyOfRange(left, 1, left.length);
}
while (right.length > 0) {
result[i++] = right[0];
right = Arrays.copyOfRange(right, 1, right.length);
}
return result;
}
//TODO 快速排序
public static int[] test6(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
return quickSort(arr, 0, arr.length - 1);
}
private static int[] quickSort(int[] arr, int left, int right) {
if (left < right) {
int partitionIndex = partition(arr, left, right);
quickSort(arr, left, partitionIndex - 1);
quickSort(arr, partitionIndex + 1, right);
}
return arr;
}
private static int partition(int[] arr, int left, int right) {
// 设定基准值(pivot)
int pivot = left;
int index = pivot + 1;
for (int i = index; i <= right; i++) {
if (arr[i] < arr[pivot]) {
swap1(arr, i, index);
index++;
}
}
swap1(arr, pivot, index - 1);
return index - 1;
}
private static void swap1(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//TODO 堆排序
public static int[] test7(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
int len = arr.length;
buildMaxHeap(arr, len);
for (int i = len - 1; i > 0; i--) {
swap2(arr, 0, i);
len--;
heapify(arr, 0, len);
}
return arr;
}
private static void buildMaxHeap(int[] arr, int len) {
for (int i = (int) Math.floor(len / 2); i >= 0; i--) {
heapify(arr, i, len);
}
}
private static void heapify(int[] arr, int i, int len) {
int left = 2 * i + 1;
int right = 2 * i + 2;
int largest = i;
if (left < len && arr[left] > arr[largest]) {
largest = left;
}
if (right < len && arr[right] > arr[largest]) {
largest = right;
}
if (largest != i) {
swap2(arr, i, largest);
heapify(arr, largest, len);
}
}
private static void swap2(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
//TODO 计数排序
public static int[] test8(int[] sourceArray) throws Exception {
// 对 arr 进行拷贝,不改变参数内容
int[] arr = Arrays.copyOf(sourceArray, sourceArray.length);
int maxValue = getMaxValue(arr);
return countingSort(arr, maxValue);
}
private static int[] countingSort(int[] arr, int maxValue) {
int bucketLen = maxValue + 1;
int[] bucket = new int[bucketLen];
for (int value : arr) {
bucket[value]++;
}
int sortedIndex = 0;
for (int j = 0; j < bucketLen; j++) {
while (bucket[j] > 0) {
arr[sortedIndex++] = j;
bucket[j]--;
}
}
return arr;
}
private static int getMaxValue(int[] arr) {
int maxValue = arr[0];
for (int value : arr) {
if (maxValue < value) {
maxValue = value;
}
}
return maxValue;
}
//TODO 桶排序
public static int[] test9(int[] arr) {
// 遍历原始数组,找到数组中的最大值
int max = arr[0];
for (int i = 0; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 创建一个下标为原始数组中最大值的桶数组,该桶数组的下标代表元素,该数组下标所对应的值代表这个值出现的次数
int[] bucketArray = new int[max + 1];
// 再次遍历原始数组,得到原数组中存在的各个元素,以及出现的次数
for (int i = 0; i < arr.length; i++) {
bucketArray[arr[i]]++;
}
// 遍历桶数组,外层循环从桶的第一位开始(即下表为零);内层循环遍历桶数组中下标为i的值出现的次数
int index = 0;
for (int i = 0; i < bucketArray.length; i++) {
for (int j = 0; j < bucketArray[i]; j++) {
arr[index++] = i;
}
}
return arr;
}
//TODO 基数排序
public static int[] test10(int[] arr) {
// 假定arr[0] 是最大数
// 1. 通过遍历arr, 找到数组中真正最大值
// 2. 目的是确定要进行多少轮排序
int max = arr[0];
for (int i = 1; i < arr.length; i++) {
if (arr[i] > max) {
max = arr[i];
}
}
// 计算最大数字是几位数
int maxLength = (max + "").length();
// 定义一个二维数组, 就是10个桶
// 1. 该二维数组有10个一维数组 0-9
// 2. 为了防止溢出,每个一维数组(桶),大小定为 arr.length
// 3. 很明确, 基数排序是空间换时间
int[][] bucket = new int[10][arr.length];
// 用于记录在每个桶中,实际存放了多少个数据,这样才能正确的取出
int[] bucketElementCounts = new int[10];
// 根据最大长度的数决定比较的次数
// 1. 大循环的次数就是 最大数有多少位,前面分析过
// 2. n = 1, n *= 10 是为了每轮循环排序时,分别求出各个元素的 个位,十位,百位,千位 ...
// 就是一个小算法
// 3. 这个基础排序,完全可以使用 冒泡分步写代码来完成,比较简单!!
for (int i = 0, n = 1; i < maxLength; i++, n *= 10) {
// 把每一个数字分别计算本轮循环的位数的值,比如第1轮是个位...
for (int j = 0; j < arr.length; j++) {
// 计算
int digitOfElement = arr[j] / n % 10;
// 把当前遍历的数据放入指定的数组中
bucket[digitOfElement][bucketElementCounts[digitOfElement]] = arr[j];
// 记录数量
bucketElementCounts[digitOfElement]++;
}
// 记录取的元素需要放的位置
int index = 0;
// 把各个桶中(10个桶)存放的数字取出来, 放入到arr中
for (int k = 0; k < bucketElementCounts.length; k++) {
// 如果这个桶中,有数据才取,没有数据就不取了
if (bucketElementCounts[k] != 0) {
// 循环取出元素
for (int l = 0; l < bucketElementCounts[k]; l++) {
// 取出元素
arr[index++] = bucket[k][l];
}
// 把这个桶的对应的记录的数据个数置为0,注意,桶本身数据(前面存的数据还在)
bucketElementCounts[k] = 0; //
}
}
}
return arr;
}
}
Java-Study_04 Array 冒泡排序
于 2022-06-18 15:30:02 首次发布