每种排序算法都有其时间复杂度、空间复杂度和稳定性等特点,根据具体场景选择合适的排序算法可以提高排序效率。
常见的的排序算法:
- 冒泡排序:通过相邻元素的比较和交换
- 选择排序:每次从没有排序部分选择最小(或最大),放到已排序部分的末尾(或开头)
- 插入排序:将未排序部分的元素逐个插入到已排序部分的合适位置,直到整个数组有序。
- 希尔排序:是插入排序的改进版本,通过设定增量序列,对间隔为增量的元素进行插入排序。
- 归并排序:采用分治思想,将数组分为两个子数组,分别排序后合并,递归进行直到整个数组有序。
- 快速排序:采用分治思想,选择一个基准元素,将小于基准的元素放在左边,大于基准的元素放在右边,递归进行排序。
- 堆排序:利用堆这种数据结构进行排序,构建最大堆或最小堆,每次取堆顶元素进行调整。
- 计数排序:适用于元素范围较小的整数排序,通过统计每个元素出现的次数,然后进行排序。
- 桶排序:将元素分配到不同的桶中,对每个桶中的元素进行排序,最后合并所有桶。
- 基数排序:按照元素的位数进行排序,从低位到高位依次进行排序,适用于整数排序。
冒泡排序:
package com.xinxin.sort; import java.util.Arrays; /** * @author weixinxin 2024-03-06 **/ public class BubbleSort { /** * @Description 冒泡排序 * @Date 15:24 2024/03/06 * @author weixinxin */ public static void BubbleSort(int[] data) { int length = data.length; for (int i = 1; i < length; i++) { for (int j = 0; j < length - 1; j++) { if (data[j] > data[j + 1]) { int temp = data[j]; data[j] = data[j + 1]; data[j + 1] = temp; } } } System.out.println("data = " + Arrays.toString(data)); } public static void main(String[] args) { int[] data = {1,5,4,8,6,9,3,2,12,25,16,18}; BubbleSort(data); } }
个人理解:
1) 首先里层的for循环,j 要理解为数组角标 2) 对于数组data,角标为(0-->data.length-1) 3) 从脚标为0的元素一直遍历到最后一个元素 4) 如果数组 data[0] > data[1] 那就要互换位置将大的值放到小值后面 5) 例:数组{10,4,5,9}; 当 i = 1 时,对于里层for循环需要遍历 3 次,最大值会放到最后(第四) 当 i = 2 时,对于里层for循环需要遍历 3 次,第二大值会放到倒数第二(第三)的位置 当 i = 3 时,对于里层for循环需要遍历 3 次,第三大值会放到倒数第三(第二)的位置 当 i = 4 时,对于里层for循环需要遍历 3 次,最小值会放到第一的位置
选择排序:
package com.xinxin.sort; import java.util.Arrays; /** * @author weixinxin 2024-03-06 **/ public class SelectionSort { /** * @Description 选择排序 * @Date 16:40 2024/03/06 * @author weixinxin */ public static void selectionSort(int[] data) { for (int i = 0; i < data.length-1; i++) { int minIndex = i; for (int j = i+1; j < data.length; j++) { if (data[minIndex] > data[j]){ minIndex = j; } } int temp = data[i]; data[i] = data[minIndex]; data[minIndex] = temp; } System.out.println("data = " + Arrays.toString(data)); } public static void main(String[] args) { int[] data = {55, 27, 19, 22, 7}; selectionSort(data); } }
个人理解:
1)对于选择排序,两次for循环的 i 和 j 都要理解为数组角标
2)里层for循环,首先定义了minIndex最小元素角标
3)当 i = 0 时,里层for循环遍历,前与后比较,将最小元素角标找到
4)直到找到最小元素角标,将最小元素角标放到第一位
5)例如:数组{55,27,19,22,7}
当 i = 0 时,minIndex = 4 ,data[0] = 7,此时数组为{7,27,19,22,55}
当 i = 1 时,minIndex = 2 ,data[0] = 19,此时数组为{7,19,27,22,55},此时的元素 7 不会参加比较
插入排序:
package com.xinxin.sort; import java.util.Arrays; /** * @author weixinxin 2024-03-07 **/ public class InsertionSort { /** * @Description 插入排序 * @Date 14:07 2024/03/07 * @author weixinxin */ public static void insertionSort(int[] data) { for (int i = 1; i < data.length; i++) { int key = data[i]; int j = i - 1; while ( j>=0 && data[j] > key) { data[j+1] = data[j]; j--; } data[j+1] = key; } System.out.println("data = " + Arrays.toString(data)); } public static void main(String[] args) { int[] data = {6, 9, 4, 2, 1}; insertionSort(data); } }
对一个整型数组进行排序。插入排序的基本思想是将未排序部分的元素逐个插入到已排序部分的合适位置,直到整个数组有序。
希尔排序:
package com.xinxin.sort; import java.util.Arrays; /** * @author weixinxin 2024-03-07 **/ public class ShellSort { /** * @Description 希尔排序 * @Date 14:11 2024/03/07 * @author weixinxin */ public static void shellSort(int[] data) { int n = data.length; // 初始步长设定为数组长度的一半 for (int gap = n / 2; gap > 0; gap /= 2) { for (int i = gap; i < n; i++) { int temp = data[i]; int j = i; // 对间隔为gap的元素进行插入排序 while (j >= gap && data[j - gap] > temp) { data[j] = data[j - gap]; j -= gap; } data[j] = temp; } } System.out.println("data = " + Arrays.toString(data)); } public static void main(String[] args) { int[] data = {12, 34, 54, 2, 3}; shellSort(data); } }
希尔排序是插入排序的改进版本,通过设定增量序列,对间隔为增量的元素进行插入排序。在代码中,我们首先设定一个初始步长(增量),然后逐步缩小步长直至为1,对每个步长进行插入排序。希尔排序的时间复杂度取决于增量序列的选择,通常比插入排序快,但不稳定
归并排序:。。后续