一、导入:为什么叫冒泡排序
大家都烧过水吧,是不是每次水快要开的时候烧水容器的底部都会‘咕嘟~’‘咕嘟~’的往上冒泡,先是粘在底部的小泡,在其上升过程中逐渐变大,在达到峰值时啪一下的破裂开来。
冒泡排序的就是这一现象的代码版,算法中的一侧元素会像小气泡一样一点一点的向另一侧移动,当从一侧移动到另一侧时元素小气泡便会都达到峰值,而不一样的是这个峰值可大可小。
比如我们有这样一组数据,整形数组array={1,9,3,8,7,2,6,5,4},我们将数组下标当作从低到高的‘刻度’,而其中的元素当作大小不一的气泡,我们‘底部’开始向上两两比较,让较大的气泡‘超越’较小的气泡,最后在‘顶部’得到一个最大的气泡,如下图:
再重复这个过程,得到次级最大值:
二、冒泡排序算法
冒泡排序(Bublle Sort)是一种基础的交换排序,其思想是把相邻的元素两两比较,当一个元素大(小)于右侧相邻元素时,交换他们的位置;当一个元素小(大)于或等于右侧相邻元素时,位置不变。
以升序排序为例,按照冒泡排序思想从最左侧两两相比至最后一个元素,这一过程是将比过部分最大值不断后移冒泡的过程,不断重复这一过程就会使最右侧有序区间不断扩大(++),最终使数据集整体有序。
当经过n-1轮后所有元素有序,如图:
public void bubbleSort(int[] array) {
//共比较n-1轮
for(int i = 0; i < array.length-1; i++) {
//有序区间无需排序
for(int j = 1; j < array.length-i; j++ ) {
//若右侧元素大于左侧,则交换位置
if(array[j] < array[j-1]) {
//交换
swap(array, j-1, j);
}
}
}
}
三、冒泡排序算法复杂度分析
冒泡排序算法是为数不多的稳定的排序算法,而其算法的比较次数同样稳定,交换次数在最坏情况下,即逆序情况下要使数据集升序排序,那么每次比较都会进行一次交换,共进行(n-1)+(n-2)+...+3+2+1次。
因此排序算法的时间复杂度应是O(N^2)。
排序过程都在数据集内部操作并不需要额外的空间,因此空间复杂度为O(1)
四、冒牌排序的优化
在最好情况下,即顺序情况下要使数据集升序排序,因为其本身有序,那么每次比较都无需进行交换,这就会造成极大的时间浪费,其实我们只需要判断n-1次确定其是否已经有序即可。
除了本身有序的情况,排序过程中也可能在程序执行过程中就有序了,无需继续判断下去,那么后面这部分时间同样可以省略下来。
优化:每轮排序的同时判断本轮是否进行过交换,若未进行过,则证明已经有序
public void bubbleSort(int[] array) {
//共比较n-1轮
for(int i = 0; i < array.length-1; i++) {
boolean b = true;
//有序区间无需排序
for(int j = 1; j < array.length-i; j++ ) {
//若右侧元素大于左侧,则交换位置
if(array[j] < array[j-1]) {
//交换
swap(array, j-1, j);
b = false;
}
}
if(b) {
break;
}
}
}
博主是Java新人,每位同志的支持都会给博主莫大的动力,如果有任何疑问,或者发现了任何错误,都欢迎大家在评论区交流“ψ(`∇´)ψ