java基础:14.2 排序算法


 

插入排序 = 选择排序 = 冒泡排序 = 快速排序 / 的最差时间复杂度 = O(n^2)
归并排序 / 最差、平均复杂度 = O(nlogn)
快读排序 / 平均复杂度 = O(nlogn)
堆排序 = O(nlogn)


 
 

1、冒泡排序(Bubble Sort)

原理
冒泡排序是这样实现的:
1、从列表的第一个数字到倒数第二个数字,逐个检查:若某一位上的数字大于他的下一位,则将它与它的下一位交换。
2、重复1号步骤,直至再也不能交换。
冒泡排序的平均时间复杂度与插入排序相同,也是O(n^2),但冒泡排序是原地排序的,也就是说它不需要额外的存储空间

时间复杂度
冒泡排序算法多次遍历数组,在每次逼历中连续比较相邻的元素,如果元素没有按照顺序排列,则互换它们的值。

外层循环执行 N - 1次。内层循环最多的时候执行N次,最少的时候执行1次,平均执行 (N+1)/2次。
所以循环体内的比较交换约执行 (N - 1)(N + 1) / 2 = (N^2 - 1)/2(其中^2是仿照Latex中的记法,表示N的平方)。按照计算复杂度的原则,去掉常数,去掉最高项系数,其复杂度为O(N^2)。

	public static void bubble(int[] list) {
   
		for(int i=0; i<list.length; i++) {
   
			for(int j=0; j<list.length-i-1 ; j++) {
   
				if(list[j]>list[j+1]) {
   
					int temp = list[j+1];
					list[j+1] = list[j];
					list[j] = temp;
				}
			}
		}
	}

注意到如果在某次遍历中没有发生交换,那么就不必进行下一次遍历,因为所有的元素都已经排好序了。

	public static void improve_bubble(int[] list) {
   
		boolean needNextPass = true;
		
		for(int i=1; i<list.length && needNextPass ; i++) {
   
			needNextPass = false;
			for(int j=0; j<list.length- i ; j++) {
   
				if(list[j]>list[j+1]) {
   
					int temp = list[j+1];
					list[j+1] = list[j];
					list[j] = temp;
					
					needNextPass = true;
				}
			}
		}
	}

 
 

2、选择排序(Selection Sort)

思考
冒泡排序每一次把最大值转移值挪到最前端时,进行了很多次小的交换。
选择排序和冒泡排序的区别:每一次把最大值转移值挪到最前端时,只要进行一次交换!

原理
每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置(末尾位置),然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到全部待排序的数据元素排完。 选择排序是不稳定的排序方法。
选择排序是这样实现的:

1、设数组内存放了n个待排数字,数组下标从1开始,到n结束。
2、初始化i=1
3、从数组的第i个元素开始到第n个元素,寻找最小的元素。
4、将上一步找到的最小元素和第i位元素交换。
5、i++,直到i=n-1算法结束,否则回到第3步
选择排序的平均时间复杂度也是O(n^2)的。

时间复杂度
每一趟从待排序的记录中选出最小的元素,顺序放在已排好序的序列最后,直到全部记录排序完毕。也就是:
共n次迭代,在第k次迭代中:
selectMax()需要O(n-k)
remove()和insertBefor()均为O(1)
所以总体复杂度为O(n^2)

每一趟在n-i+1 (i=1,2,…n-1)个记录中选取关键字最小的记录作为有序序列中第i个记录。基于此思想的算法主要有简单选择排序、树型选择排序和堆排序。(这里只介绍常用的简单选择排序)

选择排序的交换操作介于 0 和 n-1次之间。选择排序的比较操作为 n (n - 1) / 2 次之间。选择排序的赋值操作介于 0 和 3 (n - 1) 次之间。
比较次数O(n^2),比较次数与关键字的初始状态无关,总的比较次数N=(n-1)+(n-2)+…+1=n*(n-1)/2。交换次数O(n),最好情况是,已经有序,交换0次;最坏情况交换n-1次,逆序交换n/2次。

交换次数(移动操作)比冒泡排序少多了,由于交换所需CPU时间比比较所需的CPU时间多,n值较小时,选择排序比冒泡排序快。

	public static void selectSort(int[]a)
	{
   
	    int minIndex=0;
	    int temp=0;
	    if((a==null)||(a.length==0))
	        return;
	    for(int i=0;i<a.length;i++)
	    {
   
	        minIndex=i;//无序区的最小数据数组下标
	        for(int  j=i+1;j<a.length;j++)
	            if(a[j]<a[minIndex])   //在无序区中找到最小数据并保存其数组下标
	                minIndex=j;
	        temp=a[i]; 	//将最小元素放到本次循环的前端
	        a[i]=a[minIndex];
	        a[minIndex]=temp;
	    }
	}

 
 

3、插入排序(Insertion Sort)

原理
插入排序重复地将新的元素插入到一个排好序的子线性表中,直到整个线性表排好序。

插入排序是这样实现的:
1、首先新建一个空列表,用于保存已排序的有序数列(我们称之为"有序列表")。
2、从原数列中取出一个数,将其插入"有序列表"中,使其仍旧保持有序状态。
3、重复2号步骤&#

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值