十大经典排序算法以及部分优化

本文详细介绍了十大经典排序算法:冒泡排序、选择排序、插入排序、希尔排序、归并排序、快速排序、堆排序、计数排序、桶排序和基数排序。包括它们的基本思想、算法描述、时间复杂度、空间复杂度、优化实现和总结。对于每个算法,还提供了算法动图演示和Java代码实现。文章最后总结了排序算法的选择依据,如稳定性、时间复杂度和适用场景。
摘要由CSDN通过智能技术生成

参考:https://www.cnblogs.com/guoyaohua/p/8600214.html?tdsourcetag=s_pcqq_aiomsg

在这里插入图片描述

1.冒泡排序(Bubble Sort)

1.1基本思想

两两比较大小,大的沉下去(放后面),小的浮起来(放前面)。

1.2算法描述

  • 比较相邻的两个数,如果第一个大就交换位置
  • 对每一对相邻的元素做比较,这样最大的数就在最后的位置
  • 重复以上步骤,除了最后已经排好序的数
  • 重复步骤1~3,直到排序完成

1.3动图演示
冒泡
1.4算法分析

  • 平均时间复杂度 O(n^2) ,最佳情况O(n), 最差情况O(n^2)
    空间复杂度 O(1)

1.5JAVA代码实现

public static int[] bubbleSort(int[] array){
	if(array.length == 0){
		return array;
	}
	for(int i=0;i<array.length-1;i++){		//比较a.length-1轮即可,比较一轮找到一个
		for(int j=0;j<array.length-1-i;j++){		//无序区间[0,a.length-1-i)
			if(array[j+1]<array[j]){
				int temp = array[j+1];
				array[j+1] = array[j];
				array[j] = temp;
			}
		}
	}
	return array;
}

如果你对循环的边界设定不清楚,可以看下这张图:
循环的思路
1.6算法优化实现

  1. 每次比较都使用一个temp变量,同一个空间。
  2. 如果外层循环循环一次内层都没有发生交换,即比较一轮都没有交换的说明数组有序。
  3. 内层循环时,如果最后有几次并没有交换,说明只需要比较到上次交换的位置即可。
public static int[] bubbleSort(int[] array){
	if(array.length == 0){
		return array;
	}
	int temp;
	int changeIndex = 0;	//最后一次交换的位置
	int sortIndex = array.length;	//无序区间的边界
	for(int i=0;i<array.length-1;i++){		
		boolean flag = true;	//优化2
		for(int j=0;j<sortIndex;j++){		
			if(array[j+1]<array[j]){
				temp = array[j+1];
				array[j+1] = array[j];
				array[j] = temp;
				changeIndex = j;	//记录最后一次发生交换的位置
				flag = false;	//发生了交换
			}
		}
		sortIndex = changeIndex;	//改变无序区间的边界
		if(flag){	//这一轮一次交换都没有发生,数组有序
			return array;
		}
	}
	return array;
}

1.7总结

  • 使用场景:适用元素较少的情况下和数组基本有序的情况
  • 优点:简单,空间复杂度低,稳定
  • 缺点:时间复杂度高,效率慢

*2.选择排序(Selection Sort) *

2.1基本思想

表现最稳定的排序算法之一,在未排序序列中找到最小的元素存放在序列的起始位置,再从剩余未排序序列中继续寻找最小的元素,然后放到已排序序列的末尾,重复执行。

2.2算法描述

  • n个元素,初始时:无序区间R[1…n],有序区间为空;
  • 到第i趟开始时,有序区间R[1…i-1],无序区间R[i…n]。然后从无序区间找到最小的数和无序区间第一个数交换,这时有序区间变为R[1…i],无序区间变为R[i+1…n];
  • n-1趟结束后,数组有序。

2.3动图演示

快速排序
2.4算法分析

  • 平均时间复杂度 O(n^2) ,最佳情况O(n^2), 最差情况O(n^2)
    空间复杂度 O(1)

2.5JAVA代码实现

public static int[] selectionSort(int[] array){
	if(array.length == 0){
		return array;
	}
	for(int i = 0;i < array.length;i++){
		int minIndex = i;
		for(int j = i, j < array.length;j++){
			if(array[j] < array[mindex]){
				minIndex = j;
			}
		}
		int temp = array[minIndex];
		array[minIndex] = array[i];
		array[i] = temp;
	}
	return array;
}		

2.6算法优化实现

选择排序是一次确定一个元素的位置,而选择排序的优化则是一次确定两个元素的位置,比如降序:每次将最小值放在起始位置,最大值放在末尾位置。这样外层循环的时间缩短了一半,性能也提高了很多。

public static int[] sort(int[] a) {
		if(a.length == 0) {
			return a;
		}
		int left = 0;
        int right = a.length - 1;
		while(left < right) {
			int minIndex = left;
		 	int maxIndex = left;
			for(int j=left;j <= right;j++) {
				minIndex = a[j] < a[minIndex] ? j : minIndex;
				maxIndex = a[j] > a[maxIndex] ? j : maxIndex;
			}
			if(minIndex != left) {
				int temp = a[minIndex];
				a[minIndex] = a[left];
				a[left] = temp;
			}
			 //如果最大元素下标是left,但是前面已经和最小元素交换了,则此时最大元素下标应该是min
            if (maxIndex == left){
            	maxIndex = minIndex;
            }
            //如果max就是最小的则不用交换
            if (maxIndex != right){
                int tmp = a[right];
                a[right] = a[maxIndex];
                a[maxIndex] = tmp;
            }
            left++;
            right--;	
		}		
		return a;
	}

2.7总结

  • 使用场景:适用元素较少的情况下和数组基本有序的情况
  • 优点:交换次数少,移动次数确定n次
  • 缺点:效率慢,不稳定

*3.插入排序(Insertion Sort) *

3.1基本思想

通过构建有序序列,对未排序的数据从有序序列中从后向前扫描,找到相应位置插入。在这个过程中,需要一直将已排序元素向后移动来为新元素提供空间。

3.2算法描述

  • 将第一个数和第二个数排序࿰
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值