冒泡排序的原理,优化 以及实现过程的Java源代码

目录

1.什么是冒泡排序?

2.原始冒泡排序的Java代码实现

3.原始冒泡排序的优化方案一

4.原始冒泡排序的优化方案二


1.什么是冒泡排序?

       冒泡排序的英文是bubble sort,是一种最基础的交换顺序。在可口可乐里面常常有许多小小的气泡飘到上面来,这是因为组成小气泡的二氧化碳比水的密度小,所以小气泡可以一点一点向上移动。而我们的冒泡排序之所以叫做冒泡排序就是因为这种排序算法的每一个元素都可以像小气泡一样根据自身大小一点一点向数组的一侧移动。

       具体如何移动看下面的例子:

  

        以上是由8个数组成的一个无序数列,我们希望它可以从小到大排序。按照冒泡排序的思想,我们要把相邻的元素两两比较,根据大小来交换位置,过程如下:

                    

   

  

  

  至此,元素9已经是数列中的最大元素,就像可乐里的小气泡一样一直飘到最右侧。这个时候我们的冒泡排序的第一轮结束,数组最右侧的元素9即可认为是一个有序区域,有序区域目前只有一个元素。

  以此类推,第二轮排序结束后我们数列右侧的有序区有了两个元素分别是8和9,顺序如下:

第三轮排序结束后数列右侧的有序区有了三个元素分别是7,8,9.其中顺序如下:

第四轮排序结束后数列右侧的有序区有了四个元素分别是6,7,8,9,其顺序如下:

第五轮排序结束后数列右侧的有序区有了五个元素分别是5,6,7,8,9,其顺序如下:

第六轮排序结束后数列右侧的有序区有了六个元素分别是3,5,6,7,8,9,其顺序如下:

第七轮排序结束后数列右侧的有序区有了七个元素分别是2,3,5,6,7,8,9,其顺序如下:

第八轮排序结束后数列右侧的有序区有了八个元素分别是1,2,3,5,6,7,8,9,其顺序如下:

到此为止,所有的元素都有了顺序,这就是冒泡排序的整体思路。

以上这种原始的冒泡排序是稳定排序。由于该算法的每一轮要遍历所有的元素,轮转的次数和元素的数量相当,所以时间复杂度是O(N*N)。

2.原始冒泡排序的Java代码实现

package maopaopaixu;

public class MaoPaoPaiXu {
	public static void paixu(int array[]){
		int huan = 0;//数据交换时的中间变量
		for(int i = 0;i<array.length;i++){//外层for循环控制所有回合
			for(int j = 0;j<array.length - (i + 1);j++){//内层for循环代表每一轮的冒泡处理
				if(array[j]>array[j+1]){//进行元素比较
					//进行元素交换
					huan = array[j];
					array[j] = array[j+1];
					array[j+1] = huan;
				}
			}
		}
	}
	public static void main(String[] args) {
		int[] array = new int[]{5,8,6,3,9,2,1,7};
		paixu(array);
		for(int i = 0;i<array.length;i++){
			System.out.println(array[i]);
		}
	} 
}

其运行结果就可以把整个数列按照从小到大的顺序输出至控制台。代码使用双循环来进行排序,外部循环控制所有的回合,内部循环代表每一轮的冒泡处理,先进行元素比较,再进行元素交换。

3.原始冒泡排序的优化方案一

       回顾一下刚刚描述的排序细节,当排序算法分别执行到第6,7,8轮的时候,整个数列就已经有了正确的顺序,但是算法依然继续了第七轮和第八轮。这种情况下,如果我们能判断出数列已经有序,并且做出标记,剩下的几轮排序就可以不必执行。

package maopaopaixu;

public class MaoPaoPaiXu {
	public static void paixu(int array[]){
		int huan = 0;//数据交换时的中间变量
		boolean panduan = true;//有序标记
		for(int i = 0;i<array.length-1;i++){//外层for循环控制所有回合
			for(int j = 0;j<array.length - (i + 1);j++){//内层for循环代表每一轮的冒泡处理
				if(array[j]>array[j+1]){//进行元素比较
					//进行元素交换
					huan = array[j];
					array[j] = array[j+1];
					array[j+1] = huan;
					panduan = false;//如果进入if循环,就说明有元素交换,所以不是有序,便将标记变为false
				}
			}
			if(panduan){//如果元素交换没有发生,则有序标记为true,退出外层for循环,下面的回合不再执行
				break;
			}
		}
	}
	public static void main(String[] args) {
		int[] array = new int[]{5,8,6,3,9,2,1,7};
		paixu(array);
		for(int i = 0;i<array.length;i++){
			System.out.println(array[i]);
		}
	} 
}

此优化的核心思想就是如果本轮排序中元素有交换,那么就说明数列无序,如果没有元素交换,就说明数列已经有序,便直接跳出大循环。

4.原始冒泡排序的优化方案二

      找一个新的数列:

34215678

这个数列的特点是:前半部分(3,4,2,1)无序,后半部分(5,6,7,8)升序,并且后半部分的元素已经是数列的最大值。而用之前的排序算法的话,就会进行几次无用的元素比较。其主要原因就在于对数列有序区的界定。按照现有的逻辑,有序区的长度和排序的轮数是相等的。比如第一轮排序过后的有序区的长度是1,第二轮排序过后的有序区的长度是2,,,,,,实际上,数列的真正的有序区可能会大于这个长度。而避免这种情况出现的方法就是:记录下最后一次元素交换的位置,那个位置也就是无序数列的边界,再往后就是有序区了。

代码如下:

package maopaopaixu;

public class MaoPaoPaiXu {
	public static void paixu(int array[]){
		int tmp = 0;
		int lastExchangeIndex = 0;
		int sortBorder = array.length - 1;//无序数列的边界,每次比较只需要比到这里为止
		for(int i = 0;i<array.length;i++){
			boolean isSorted = true;//有序标记,每一轮的初始都是true
			for(int j = 0;j<sortBorder;j++){
				if(array[j]>array[j+1]){
					tmp = array[j];
					array[j] = array[j+1];
					array[j+1] = tmp;
					isSorted = false;//有元素交换,所以不是有序,标记变为false
					lastExchangeIndex = j;//把无序数列的边界更新为最后一次交换元素的位置
				}
			}
			sortBorder = lastExchangeIndex;
			if(isSorted){
				break;
			}
		}
		
		
	}
	public static void main(String[] args) {
		int[] array = new int[]{3,4,2,1,5,6,7,8};
		paixu(array);
		for(int i = 0;i<array.length;i++){
			System.out.println(array[i]);
		}
	} 
}

 

冒泡排序-排序过程 设想被排序的数组R[1..N]垂直竖立,将每个数据元素看作有重量的气泡,根据轻气泡不能在重气泡之下的原则,从下往上扫描数组R,凡扫描到违反本原则的轻气泡,就使其向上"漂浮",如此反复进行,直至最后任何两个气泡都是轻者在上,重者在下为止。 算法示例 49 13 13 13 13 13 13 13 38 49 27 27 27 27 27 27 65 38 49 38 38 38 38 38 97 65 38 49 49 49 49 49 76 97 65 49 49 49 49 49 13 76 97 65 65 65 65 65 27 27 76 97 76 76 76 76 49 49 49 76 97 97 97 97 Procedure BubbleSort(Var R : FileType) //从下往上扫描的起泡排序// Begin For I := 1 To N-1 Do //做N-1趟排序// begin NoSwap := True; //置未排序的标志// For J := N - 1 DownTo 1 Do //从底部往上扫描// begin If R[J+1]< R[J] Then //交换元素// begin Temp := R[J+1]; R[J+1 := R[J]; R[J] := Temp; NoSwap := False end; end; If NoSwap Then Return//本趟排序中未发生交换,则终止算法// end End; //BubbleSort// 该算法的时间复杂性为O(n2),算法为稳定的排序方 冒泡排序-冒泡排序法的改进 比如用冒泡排序将4、5、7、1、2、3这6个数排序。在该列中,第二趟排序结束后,数组已排好序,但计算机此时并不知道已经反排好序,计算机还需要进行一趟比较,如果这一趟比较,未发生任何数据交换,则知道已排序好,可以不再进行比较了。因而第三趟比较还需要进行,但第四、五趟比较则是不必要的。为此,我们可以考虑程序的优化。 为了标志在比较中是否进行了,设一个布尔量flag。在进行每趟比较前将flag置成true。如果在比较中发生了数据交换,则将flag置为false,在一趟比较结束后,再判断flag,如果它仍为true(表明在该趟比较中未发生一次数据交换)则结束排序,否则进行下一趟比较。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值