十大排序方法
1、冒泡排序
/**
* @author Honey
* @date 2021/8/8
*/
public class BubbleSort {
public static void main(String[] args) {
int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
// 接下来三个方法任选一个来进行排序,要注掉两个
sort(a);
sortArray(a,a.length-1,1);
goodSort(a);
System.out.println(Arrays.toString(a));
}
/**
* 非递归
* @param arr 排序的数组
*/
private static void sort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j + 1] < arr[j]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
}
}
}
}
/**
* 递归实现
* @param array 需要排序的数组
* @param m array.length - 1 递减
* @param n 从 1 开始到 m 递增
*/
public static void sortArray(int[] array, int m, int n) {
if (m > 0) {
if (array[n] < array[n - 1]) {
int temp = array[n];
array[n] = array[n - 1];
array[n - 1] = temp;
}
if (n >= m) {
sortArray(array,m - 1,1);
} else {
sortArray(array,m,n + 1);
}
}
}
/**
* 冒泡排序的优化,如果在排的过程中有序,则会立即返回
* @param arr 排序的数组
*/
public static void goodSort(int[] arr) {
boolean flag;
for (int i = 0; i < arr.length - 1; i++) {
System.out.println("第" + (i + 1) + "轮");
flag = true;
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j + 1] < arr[j]) {
int temp = arr[j + 1];
arr[j + 1] = arr[j];
arr[j] = temp;
flag = false;
}
}
if (flag) {
return;
}
}
}
}
2、选择排序
时间复杂度和冒泡一样,但是排序的时间要比冒泡快
/**
* @author Honey
* @date 2021/8/8
*/
public class SelectSort {
public static void main(String[] args) {
int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
selectSort(a);
goodSelectSort(a);
System.out.println(Arrays.toString(a));
}
/**
* 选择排序
* @param array 排序数组
*/
public static void selectSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int minIndex = i;
// 找到未排序数的最小值
for (int j = i; j < array.length; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
}
// 让最小值跟第 i 个值交换,第 i 个前面的值是已排好顺序的。
int temp1 = array[minIndex];
array[minIndex] = array[i];
array[i] = temp1;
}
}
/**
* 选择排序优化,双向选择排序
* @param array 排序数组
*/
public static void goodSelectSort(int[] array) {
for (int i = 0; i < array.length; i++) {
int minIndex = i;
int maxIndex = array.length - 1 - i;
// 找到未排序数的最小值
for (int j = i; j < array.length - 1 - i; j++) {
if (array[j] < array[minIndex]) {
minIndex = j;
}
if (array[j] > array[maxIndex]) {
maxIndex = j;
}
}
// 让最小值跟第 i 个值交换,第 i 个前面的值是已排好顺序的。
int temp1 = array[minIndex];
array[minIndex] = array[i];
array[i] = temp1;
int temp2 = array[maxIndex];
array[maxIndex] = array[array.length - 1 - i];
array[array.length - 1 - i] = temp2;
}
}
}
3、插入排序
/**
* @author Honey
* @date 2021/8/8
*/
public class InsertionSort {
public static void main(String[] args) {
int[] a = {1, 6, 5, 3, 13, 7, 11, 9};
insertionSort(a);
System.out.println(Arrays.toString(a));
}
/**
* 插入排序
* @param array 排序的数组
*/
public static void insertionSort(int[] array) {
int currenrt;
for (int i = 0; i < array.length - 1; i++) {
currenrt = array[i + 1];
int preIndex = i;
// 把大于current的值往后挪一位,再把current的值插入进去
while (preIndex >= 0 && currenrt < array[preIndex]) {
array[preIndex + 1] = array[preIndex];
preIndex--;
}
array[preIndex + 1] = currenrt;
}
}
}
4、希尔排序
/**
* @author Honey
* @date 2021/8/8
*/
public class ShellSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
sort(array);
System.out.println(Arrays.toString(array));
}
/**
* 排序的方法
* @param array 排序的数组
*/
public static void sort(int[] array) {
List<Integer> integers = shellStepSequence(array);
for (Integer integer : integers) {
shellSort(integer,array);
}
}
/**
* 通过出入的步长序列值的数组,进行排序
* @param step 步长序列的值
* @param array 排序数组
*/
private static void shellSort(int step,int[] array) {
for (int i = 0; i < step; i++) {
for (int begin = i + step; begin < array.length; begin += step) {
int cur = begin;
while (cur > i && array[cur] < array[cur - step]) {
int temp = array[cur];
array[cur] = array[cur - step];
array[cur - step] = temp;
cur -= step;
}
}
}
}
/**
* 通过传入的数组判断需要的步长序列
* 希尔本人给出的步长序列算法 n/2的k次方
* @param array 传入需要排序的数组
* @return 返回一个步长序列集合List<Integer>
*/
private static List<Integer> shellStepSequence(int[] array) {
List<Integer> stepSequence = new ArrayList<>();
int step = array.length;
while ((step >>= 1) > 0) {
stepSequence.add(step);
}
return stepSequence;
}
}
优化后计算步长序列的方法:
/**
* 优化后计算步长序列的公式
* @param count 传入需要排序的数组的长度
* @return 返回一个步长序列集合List<Integer>
*/
private static List<Integer> sedgewickStepSequence(int count) {
List<Integer> stepSequence = new ArrayList<>();
int k = 0;
int step = 0;
while (true) {
if (k % 2 == 0) {
int pow = (int)Math.pow(2,k >> 1);
step = 1 + 9 * (pow * pow - pow);
} else {
int pow1 = (int) Math.pow(2, (k - 1) >> 1);
int pow2 = (int) Math.pow(2, (k + 1) >> 1);
step = 1 + 8 * pow1 * pow2 - 6 * pow2;
}
if (step >= count) {
break;
}
stepSequence.add(0,step);
k++;
}
return stepSequence;
}
5、归并排序
/**
* @author Honey
* @date 2021/9/20
*/
public class MergeSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
int[] ints = MergeSort(array);
System.out.println(Arrays.toString(ints));
}
public static int[] MergeSort(int[] array) {
if (array.length < 2) {
return array;
}
int mid = array.length >> 1;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(MergeSort(left), MergeSort(right));
}
/**
* 归并排序——将两段排序好的数组结合成一个排序数组
* @param left
* @param right
* @return
*/
public static int[] merge(int[] left, int[] right) {
int[] result = new int[left.length + right.length];
for (int index = 0, i = 0, j = 0; index < result.length; index++) {
if (i >= left.length) {
result[index] = right[j++];
} else if (j >= right.length) {
result[index] = left[i++];
} else if (left[i] > right[j]) {
result[index] = right[j++];
} else {
result[index] = left[i++];
}
}
return result;
}
}
6、快速排序
/**
* @author Honey
* @date 2021/9/20
*/
public class QuickSort {
private static int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
public static void main(String[] args) {
sort(0,array.length);
System.out.println(Arrays.toString(array));
}
public static void sort(int begin, int end) {
if (end - begin < 2) {
return;
}
// 确定轴点位置
int mid = pivotIndex(begin, end);
// 对子序列进行快速排序
sort(begin,mid);
sort(mid + 1,end);
}
/**
* 确定 [begin,end) 的轴点位置
* @return 轴点元素的最终位置
*/
private static int pivotIndex(int begin, int end) {
// 备份begin位置的元素
int pivot = array[begin];
// end要指向最后一个元素
end--;
while (begin < end) {
while (begin < end) {
// 从右往左
if (pivot < array[end]) {
// 右边元素 > 轴点元素
end--;
} else {
// 右边元素 < 轴点元素
array[begin++] = array[end];
break;
}
}
while (begin < end) {
// 从左往右
if (pivot > array[begin]) {
begin++;
} else {
array[end--] = array[begin];
break;
}
}
}
// 将轴点元素放入最终的位置
array[begin] = pivot;
// 返回轴点的位置
return begin;
}
}
7、堆排序
/**
* @author Honey
* @date 2021/9/20
*/
public class HeapSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
HeapSort(array);
System.out.println(Arrays.toString(array));
}
//声明全局变量,用于记录数组array的长度;
static int len;
/**
* 堆排序算法
*
* @param array
* @return
*/
public static void HeapSort(int[] array) {
len = array.length;
if (len < 1) {
return;
}
//1.构建一个最大堆
buildMaxHeap(array);
//2.循环将堆首位(最大值)与末位交换,然后在重新调整最大堆
while (len > 0) {
swap(array, 0, len - 1);
len--;
adjustHeap(array, 0);
}
return;
}
/**
* 建立最大堆
* @param array
*/
public static void buildMaxHeap(int[] array) {
//从最后一个非叶子节点开始向上构造最大堆
for (int i = (len/2 - 1); i >= 0; i--) {
//感谢 @让我发会呆 网友的提醒,此处应该为 i = (len/2 - 1)
adjustHeap(array, i);
}
}
/**
* 调整使之成为最大堆
* @param array
* @param i
*/
public static void adjustHeap(int[] array, int i) {
int maxIndex = i;
//如果有左子树,且左子树大于父节点,则将最大指针指向左子树
if (i * 2 < len && array[i * 2] > array[maxIndex]) {
maxIndex = i * 2;
}
//如果有右子树,且右子树大于父节点,则将最大指针指向右子树
if (i * 2 + 1 < len && array[i * 2 + 1] > array[maxIndex]) {
maxIndex = i * 2 + 1;
}
//如果父节点不是最大值,则将父节点与最大值交换,并且递归调整与父节点交换的位置。
if (maxIndex != i) {
swap(array, maxIndex, i);
adjustHeap(array, maxIndex);
}
}
private static void swap(int[] array, int maxIndex, int i) {
int temp = array[maxIndex];
array[maxIndex] = array[i];
array[i] = temp;
}
}
8、计数排序
/**
* 适合对一定范围的整数进行排序
* 统计每个整数在序列中出现的次数,进而推导出每个整数在有序序列中的索引
* @author Honey
* @date 2021/9/20
*/
public class CountingSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
CountingSort(array);
System.out.println(Arrays.toString(array));
}
/**
* 计数排序
* @param array
* @return
*/
public static void CountingSort(int[] array) {
if (array.length == 0) {
return;
}
int bias, min = array[0], max = array[0];
for (int i = 1; i < array.length; i++) {
if (array[i] > max) {
max = array[i];
}
if (array[i] < min) {
min = array[i];
}
}
bias = 0 - min;
int[] bucket = new int[max - min + 1];
Arrays.fill(bucket, 0);
for (int i = 0; i < array.length; i++) {
bucket[array[i] + bias]++;
}
int index = 0, i = 0;
while (index < array.length) {
if (bucket[i] != 0) {
array[index] = i - bias;
bucket[i]--;
index++;
} else {
i++;
}
}
return;
}
}
9、桶排序
/**
* @author Honey
* @date 2021/9/20
*/
public class BucketSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
bucketSort(array);
System.out.println(Arrays.toString(array));
}
public static void bucketSort(int[] arr){
// 计算最大值与最小值
int max = Integer.MIN_VALUE;
int min = Integer.MAX_VALUE;
for(int i = 0; i < arr.length; i++){
max = Math.max(max, arr[i]);
min = Math.min(min, arr[i]);
}
// 计算桶的数量
int bucketNum = (max - min) / arr.length + 1;
ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);
for(int i = 0; i < bucketNum; i++){
bucketArr.add(new ArrayList<Integer>());
}
// 将每个元素放入桶
for(int i = 0; i < arr.length; i++){
int num = (arr[i] - min) / (arr.length);
bucketArr.get(num).add(arr[i]);
}
// 对每个桶进行排序
for(int i = 0; i < bucketArr.size(); i++){
Collections.sort(bucketArr.get(i));
}
// 将桶中的元素赋值到原序列
int index = 0;
for(int i = 0; i < bucketArr.size(); i++){
for(int j = 0; j < bucketArr.get(i).size(); j++){
arr[index++] = bucketArr.get(i).get(j);
}
}
}
}
10、基数排序
/**
* 基数排序非常适合用于整数排序(尤其是非负整数)
* 执行流程:依次对个位数、十位数、百位数、千位数、万位数。。。进行排序(从低到高)
* @author Honey
* @date 2021/9/20
*/
public class RadixSort {
public static void main(String[] args) {
int[] array = {1, 6, 5, 3, 13, 7, 11, 9};
RadixSort(array);
System.out.println(Arrays.toString(array));
}
/**
* 基数排序
* @param array
* @return
*/
public static void RadixSort(int[] array) {
if (array == null || array.length < 2) {
return;
}
// 1.先算出最大数的位数;
int max = array[0];
for (int i = 1; i < array.length; i++) {
max = Math.max(max, array[i]);
}
int maxDigit = 0;
while (max != 0) {
max /= 10;
maxDigit++;
}
int mod = 10, div = 1;
ArrayList<ArrayList<Integer>> bucketList = new ArrayList<ArrayList<Integer>>();
for (int i = 0; i < 10; i++) {
bucketList.add(new ArrayList<Integer>());
}
for (int i = 0; i < maxDigit; i++, mod *= 10, div *= 10) {
for (int j = 0; j < array.length; j++) {
int num = (array[j] % mod) / div;
bucketList.get(num).add(array[j]);
}
int index = 0;
for (int j = 0; j < bucketList.size(); j++) {
for (int k = 0; k < bucketList.get(j).size(); k++) {
array[index++] = bucketList.get(j).get(k);
}
bucketList.get(j).clear();
}
}
return;
}
}