算法复杂度
详解Java常用排序算法(10种,含演示动画)
冒泡排序(Bubble Sort)
arr[0] 与 arr[1]比较,如果前面元素大就交换,如果后边元素大就不交换。然后依次arr[1]与arr[2]比较,第一轮将最大值排到最后一位。
第二轮arr.length-1个元素进行比较,将第二大元素排到倒数第二位。直到某一轮元素位置没有交换或者结束最后一轮结束排序。这是冒泡排序改良版本。
冒泡排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。
//冒泡排序
public void test1() {
int[] arr = {
5, 2, 8, 3, 1, 6};
//i是冒泡次数
for (int i = 0; i < arr.length - 1; i++) {
//每一轮将flag设置成true,当已经排好后直接返回,不需要进行完整个循环
boolean flag = true;
//j需要排序的元素个数
for (int j = 0; j < arr.length - i - 1; j++) {
if (arr[j] > arr[j + 1]) {
// 交换arr[j+1]和arr[j]
int temp = arr[j];
arr[j] = arr[j + 1];
arr[j + 1] = temp;
flag = false;
}
}
if(flag == true){
break;
}
}
//arr = [1, 2, 3, 5, 6, 8]
System.out.println("arr = " + Arrays.toString(arr));
}
选择排序(Selection Sort)
从数组中选择出最小值放在第一个,将之前第一个元素和最小值之前所在索引位交换,依次进行第二个、第三个…
选择排序每次从待排序的元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的元素排完。
选择排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。
//选择排序
public void test2() {
int[] arr = {
5, 2, 8, 3, 1, 6};
for (int i = 0; i < arr.length - 1; i++) {
int minIndex = i;
for (int j = i + 1; j < arr.length; j++) {
//当前元素与下一个元素比较,记录较小的索引
if (arr[j] < arr[minIndex]) {
minIndex = j;
}
}
// 交换arr[i]和arr[minIndex]
int temp = arr[i];
arr[i] = arr[minIndex];
arr[minIndex] = temp;
}
//arr = [1, 2, 3, 5, 6, 8]
System.out.println("arr = " + Arrays.toString(arr));
}
插入排序(Insertion Sort)
第一个元素天然排序;第二个元素如果比第一个小就插入到第一个前面;第三个与第一个小就插入到第一个前面,如果比第二个小就插入到第二个前面;依次类推…
插入排序是将一个记录插入到已经排好序的有序表中,从而得到一个新的、记录数增1的有序表。
插入排序的时间复杂度为O(n的2次方),这使得它在大型列表和实际应用中效率低下。但是,插入排序的实现非常简单,它在小型列表上的性能非常好。
//插入排序
public void test3() {
int[] arr = {
5, 2, 8, 3, 1, 6};
// 外部循环从第二个元素开始,
// 因为我们将第一个元素视为已排序部分
for (int i = 1; i < arr.length; i++) {
int temp = arr[i];
int j = i - 1;
// 将当前值key和前面的值进行比较,
// 如果前面的值>key 则将值往后移1位
while (j >= 0 && arr[j] > temp ) {
arr[j + 1] = arr[j];
j--;
}
// 在不小当前值temp的位置,插入当前值temp
arr[j + 1] = temp;
}
//arr = [1, 2, 3, 5, 6, 8]
System.out.println("arr = " + Arrays.toString(arr));
}
希尔排序(Shell Sort)
希尔排序是一种改进的插入排序算法,它的基本思想是将待排序的数组按照一定的间隔进行分组,对每组使用插入排序算法进行排序,然后缩小间隔,再对分组进行排序,直到间隔为1为止。
逐渐减小间隔大小的方法有助于提高排序过程的效率,可以减少比较和交换的次数。这是希尔排序算法的一个关键特点。
希尔排序的时间复杂度为O(n log n),但实际上它的性能比插入排序要好得多,特别是在大型列表上。希尔排序的性能取决于间隔序列的选择,但是目前还没有一种最优的间隔序列。
//希尔排序
public void test4() {
//第一轮比如步长为5,拿出array[i],array[i+5]...,6与5,2与7,8与9等排序后array = {6, 2, 8, 3, 1, 5,7,9,4};
//第二轮比如步长为3,第二轮拿出array[i],array[i+3]...,6与3与7,2与1与9,8与5与4,排序后array = {3, 1, 4, 6, 2, 5,7,9,8};
//第三轮比如步长为1,进行插入排序
int[] array = {
5, 2, 8, 3, 1, 6,7,9,4};
int increment = array.length / 2;
while (increment >= 1){
for (int i = increment; i < array.length; i++) {
int j = i - increment;
int temp = array[i];
// 寻找插入位置并移动数据
while (j >= 0 && array[j] > temp) {