引言
也许冒泡排序,一个刚出大学的的程序员可能写的出来,反而工作了几年的老程序员可能会写不出来,你还写的出来么?在本篇博文中,详细介绍了冒泡排序的概念,同时用数组和双向链表来实现,附带一种通俗的优化方法。笔者目前整理的一些blog针对面试都是超高频出现的。大家可以点击链接:http://blog.csdn.net/u012403290
技术点
1、冒泡排序
它重复地走访过要排序的数列,一次比较两个元素,如果他们的顺序错误就把他们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成
之所以称这种排序方式为冒泡,是因为大的元素就表示它的气泡比较大,慢慢的就会按气泡大小,把数据浮上来。
2、排序过程
假设要对如下数据进行排序:
目标待排序数据:4,6,3,1,8
排序次数 | 4,6,3,1,8 | 交换情况 | 轮数量 |
---|---|---|---|
第1次交换 | 4,6,3,1,8 | 4,6进行比较,发现6比4大,不需要交换 | 第一轮 |
第2次交换 | 4,3,6,1,8 | 6,3进行比较,发现3比6小,进行交换 | 第一轮 |
第3次交换 | 4,3,1,6,8 | 6,1进行比较,发现1比6小,进行交换 | 第一轮 |
第4次交换 | 4,3,1,6,8 | 6,8进行比较,发现8比6大,不需要交换 | 第一轮结束,最大的8已经冒泡到最上面 |
第5次交换 | 3,4,1,6,8 | 4,3进行比较,发现3比4小,进行交换 | 第二轮 |
第6次交换 | 3,1,4,6,8 | 4,1进行比较,发现1比4小,进行交换 | 第二轮 |
第7次交换 | 3,1,4,6,8 | 4,6进行比较,发现6比4大,不需要交换 | 第二轮结束,第二大的6已经冒泡到倒数第二位 |
第8次交换 | 1,3,4,6,8 | 3,1进行比较,发现1比3小,进行交换 | 第三轮 |
第9次交换 | 1,3,4,6,8 | 3,4进行比较,发现4比3大,不需要交换 | 第三轮结束,第三大的4已经冒泡到倒数第三位 |
第10次交换 | 1,3,4,6,8 | 1,3进行比较,发现3比1大,不需要交换 | 第四轮结束,排序完成 |
上面就是一次完整的冒泡排序的历程,我们分析一下:
①在上面的目标数据中,有5个数据,会进行4轮排序,所以对于N个数据的排序,必然进行N-1轮的遍历,这表示一个for循环,肯定是for(int i=0, i < target.length; i++)。
②在每一轮中会有递减的判断相邻两者的大小关系,如果关系不符合就进行交换。为什么是递减的呢?因为每一轮中都会把最大的冒泡的最后面,所以不必去判断已经有序的数据。这就表示是另外一个for循环,肯定是for(int j = 0; j< target.length - i; j++)。所以冒泡排序的核心肯定是一个嵌套for循环和相邻数据的位置交换。
3、算法分析
通过上面的分析,算法可能是for循环中嵌套一个for循环。假如说目标数据本身就是有序的,那么只需要遍历一次即可完成排序(一遍之后发现不需要交换就是有序的),那么这个时候时间复杂度就是O(N);如果目标数据是反序的,那么需要遍历N-1遍,同时在每一遍的遍历中需要一直交换相邻位置,这个时候的时间复杂度就是O(N^2)。
数组实现冒泡排序
我们就用上面提到的目标数据:4,6,3,1,8来进行排序。一下是一般的数组实现:
package com.brickworkers;
/**
*
* @author Brickworker
* Date:2017年4月24日下午12:05:43
* 关于类BubbleSort.java的描述:冒泡排序
* Copyright (c) 2017, brcikworker All Rights Reserved.
*/
public class BubbleSort {
/**
* 数组实现经典冒泡排序
*/
public static<T extends Comparable<? super T>&