排序(1)——冒泡排序

1、没有优化的冒泡排序

public static void main(String[] args) {
		//冒泡排序,显示升序排列,从小到大
		int[] arr = {9,7,5,3,1};
		/**
		 * 本次排序不考虑优化,情况如下:
		 * 排序思路:
		 * 		第一趟第一次:拿9和7比较,得到的结果 7 9 5 3 1
		 * 		第一趟第二次:拿9和5比较,得到的结果 7 5 9 3 1
		 * 		第一趟第三次:拿9和3比较,得到的结果 7 5 3 9 1
		 * 		第一趟第四次:拿9和1比较,得到的结果 7 5 3 1 9
		 * 	经过第一趟的比较,把9这个最大值排到了最后面,一共有5个元素,比较了四次
		 * 
		 * 		第二趟第一次:拿7和5比较,得到的结果 5 7 3 1 9
		 * 		第二趟第二次:拿7和3比较,得到的结果 5 3 7 1 9
		 * 		第二趟第三次:拿7和1比较,得到的结果 5 3 1 7 9
		 * 		第二趟第四次:拿7和9比较,得到的结果 5 3 1 7 9
		 *  经过第二趟的比较,把7排到了9前面,一共有5个元素,比较了四次
		 *  
		 *  	第三趟第一次:拿5和3比较,得到的结果 3 5 1 7 9
		 * 		第三趟第二次:拿5和1比较,得到的结果 3 1 5 7 9
		 * 		第三趟第三次:拿5和7比较,得到的结果 3 1 5 7 9
		 * 		第三趟第四次:拿5和9比较,得到的结果 3 1 5 7 9
		 *  经过第三趟的比较,把5排到了7前面,一共有5个元素,比较了四次
		 *  
		 *  	第四趟第一次:拿3和1比较,得到的结果 1 3 5 7 9
		 * 		第四趟第二次:拿3和5比较,得到的结果 1 3 5 7 9
		 * 		第四趟第三次:拿3和7比较,得到的结果 1 3 5 7 9
		 * 		第四趟第四次:拿3和9比较,得到的结果 1 3 5 7 9
		 *  经过第四趟的比较,把7这个排到了9前面,一共有5个元素,比较了四次
		 *  
		 *  从上面可以看出,5个元素比较了4趟,每趟比较了4次,所以得到结论,要比较arr.length-1趟和arr.length-1次
		 *  	因此要通过双层循环来处理
		 */
		for(int i = 0; i < arr.length-1 ; i++){//外层循环表示趟数
			System.out.println("---第"+(i+1)+"趟---");
			for(int j = 0; j < arr.length-1 ; j++){//内层循环表示每趟的次数
				if(arr[j]>arr[j+1]){
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
				System.out.println("第"+(j+1)+"次排序后结果"+Arrays.toString(arr));
			}
			System.out.println("第"+(i+1)+"趟排序后的结果:"+Arrays.toString(arr));
		}
		//排序完打印数组
		System.out.println("最终排序结果:"+Arrays.toString(arr));	
	}

运行程序,控制台打印如下:

---第1趟---
第1次排序后结果[7, 9, 5, 3, 1]
第2次排序后结果[7, 5, 9, 3, 1]
第3次排序后结果[7, 5, 3, 9, 1]
第4次排序后结果[7, 5, 3, 1, 9]
第1趟排序后的结果:[7, 5, 3, 1, 9]
---第2趟---
第1次排序后结果[5, 7, 3, 1, 9]
第2次排序后结果[5, 3, 7, 1, 9]
第3次排序后结果[5, 3, 1, 7, 9]
第4次排序后结果[5, 3, 1, 7, 9]
第2趟排序后的结果:[5, 3, 1, 7, 9]
---第3趟---
第1次排序后结果[3, 5, 1, 7, 9]
第2次排序后结果[3, 1, 5, 7, 9]
第3次排序后结果[3, 1, 5, 7, 9]
第4次排序后结果[3, 1, 5, 7, 9]
第3趟排序后的结果:[3, 1, 5, 7, 9]
---第4趟---
第1次排序后结果[1, 3, 5, 7, 9]
第2次排序后结果[1, 3, 5, 7, 9]
第3次排序后结果[1, 3, 5, 7, 9]
第4次排序后结果[1, 3, 5, 7, 9]
第4趟排序后的结果:[1, 3, 5, 7, 9]
最终排序结果:[1, 3, 5, 7, 9]

2、优化后的冒泡排序

从上面我们可以看到,每一趟都进行了4次比较,但是我们能看到有些比较是重复的,比如第一趟的时候已经比较过7和9了,但是第二趟的时候又比较了7和9,这就导致重复比较,效率低。我们可以优化一下,减少比较次数,提高效率。

从上面的打印结果我们可以看出,其实只要比较3次就能得到结果。第一趟的时候需要比较4次,第二趟的时候需要比较3次,,第三趟的时候比较2次,第四趟的时候比较1次就够了。也就是内层循环次数依次减少了,减少的值就是趟数的值,所以如下所示:

public static void main(String[] args) {
		//冒泡排序,显示升序排列,从小到大
		int[] arr = {9,7,5,3,1};
		/**
		 * 本次排序不考虑优化,情况如下:
		 * 排序思路:
		 * 		第一趟第一次:拿9和7比较,得到的结果 7 9 5 3 1
		 * 		第一趟第二次:拿9和5比较,得到的结果 7 5 9 3 1
		 * 		第一趟第三次:拿9和3比较,得到的结果 7 5 3 9 1
		 * 		第一趟第四次:拿9和1比较,得到的结果 7 5 3 1 9
		 * 	经过第一趟的比较,把9这个最大值排到了最后面,一共有5个元素,比较了四次
		 * 
		 * 		第二趟第一次:拿7和5比较,得到的结果 5 7 3 1 9
		 * 		第二趟第二次:拿7和3比较,得到的结果 5 3 7 1 9
		 * 		第二趟第三次:拿7和1比较,得到的结果 5 3 1 7 9
		 *  经过第二趟的比较,把7排到了9前面,一共有5个元素,比较了三次
		 *  
		 *  	第三趟第一次:拿5和3比较,得到的结果 3 5 1 7 9
		 * 		第三趟第二次:拿5和1比较,得到的结果 3 1 5 7 9
		 *  经过第三趟的比较,把5排到了7前面,一共有5个元素,比较了二次
		 *  
		 *  	第四趟第一次:拿3和1比较,得到的结果 1 3 5 7 9
		 *  经过第四趟的比较,把7这个排到了9前面,一共有5个元素,比较了一次
		 *  
		 *  从上面可以看出,5个元素比较了4趟,每趟比较了4次,所以得到结论,要比较arr.length-1趟和arr.length-1次
		 *  	因此要通过双层循环来处理
		 */
		for(int i = 0; i < arr.length-1 ; i++){//外层循环表示趟数
			System.out.println("---第"+(i+1)+"趟---");
			for(int j = 0; j < arr.length-1-i ; j++){//内层循环表示每趟的次数,这里循环的次数减去趟数j
				if(arr[j]>arr[j+1]){
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
				System.out.println("第"+(j+1)+"次排序后结果"+Arrays.toString(arr));
			}
			System.out.println("第"+(i+1)+"趟排序后的结果:"+Arrays.toString(arr));
		}
		//排序完打印数组
		System.out.println("最终排序结果:"+Arrays.toString(arr));
	}

3、存在顺序的数组进行冒泡排序

比如我们的数组int arr = {8,1,2,4,5},如果对这个数组进行升序排列的话,由于该数组的数据已经存在了一定的顺序,所以如果我们还按之前的方式进行比较,就会进行无效的操作,效率也不高。

比如,第一趟比较的时候,8跟后面的元素比较,,得到的结果{1,2,4,5,8},其实最终的结果已经产生了。如果按之前的方式,那么还会进行3趟比较。所以可以用如下的方式改写排序方法:

public static void main(String[] args) throws Exception {		
		//冒泡排序,显示升序排列,从小到大
		int[] arr = {8,1,2,4,5};
		for(int i = 0; i < arr.length-1 ; i++){//外层循环表示趟数
			System.out.println("---第"+(i+1)+"趟---");
			for(int j = 0; j < arr.length-1-i ; j++){//内层循环表示每趟的次数,这里循环的次数减去趟数j
				if(arr[j]>arr[j+1]){
					int temp = arr[j];
					arr[j] = arr[j+1];
					arr[j+1] = temp;
				}
				System.out.println("第"+(j+1)+"次排序后结果"+Arrays.toString(arr));
			}
			System.out.println("第"+(i+1)+"趟排序后的结果:"+Arrays.toString(arr));
		}
		//排序完打印数组
		System.out.println("最终排序结果:"+Arrays.toString(arr));
		
		System.out.println("--------------下面是最优的排序--------------");
		int[] arr2 = {8,1,2,4,5};
		for(int i = 0; i < arr2.length-1 ; i++){//外层循环表示趟数
			System.out.println("---第"+(i+1)+"趟---");
			boolean sort = true;//假设是有序的
			for(int j = 0; j < arr2.length-1-i ; j++){//内层循环表示每趟的次数,这里循环的次数减去趟数j
				if(arr2[j]>arr2[j+1]){
					int temp = arr2[j];
					arr2[j] = arr2[j+1];
					arr2[j+1] = temp;
					//如果进了本循环,说明进行了比较,把sort改成false
					sort = false;
				}
				System.out.println("第"+(j+1)+"次排序后结果"+Arrays.toString(arr2));
			}
			System.out.println("第"+(i+1)+"趟排序后的结果:"+Arrays.toString(arr2));
			//但是如果比较了一趟后,发现sort的值是true,说明此时数组已经是有序的,因此跳出外层循环
			if(sort){
				break;
			}
		}
		//排序完打印数组
		System.out.println("最终排序结果:"+Arrays.toString(arr2));
		
	}

结果如下:

---第1趟---
第1次排序后结果[1, 8, 2, 4, 5]
第2次排序后结果[1, 2, 8, 4, 5]
第3次排序后结果[1, 2, 4, 8, 5]
第4次排序后结果[1, 2, 4, 5, 8]
第1趟排序后的结果:[1, 2, 4, 5, 8]
---第2趟---
第1次排序后结果[1, 2, 4, 5, 8]
第2次排序后结果[1, 2, 4, 5, 8]
第3次排序后结果[1, 2, 4, 5, 8]
第2趟排序后的结果:[1, 2, 4, 5, 8]
---第3趟---
第1次排序后结果[1, 2, 4, 5, 8]
第2次排序后结果[1, 2, 4, 5, 8]
第3趟排序后的结果:[1, 2, 4, 5, 8]
---第4趟---
第1次排序后结果[1, 2, 4, 5, 8]
第4趟排序后的结果:[1, 2, 4, 5, 8]
最终排序结果:[1, 2, 4, 5, 8]
--------------下面是最优的排序--------------
---第1趟---
第1次排序后结果[1, 8, 2, 4, 5]
第2次排序后结果[1, 2, 8, 4, 5]
第3次排序后结果[1, 2, 4, 8, 5]
第4次排序后结果[1, 2, 4, 5, 8]
第1趟排序后的结果:[1, 2, 4, 5, 8]
---第2趟---
第1次排序后结果[1, 2, 4, 5, 8]
第2次排序后结果[1, 2, 4, 5, 8]
第3次排序后结果[1, 2, 4, 5, 8]
第2趟排序后的结果:[1, 2, 4, 5, 8]
最终排序结果:[1, 2, 4, 5, 8]

可以从结构看出,之前的方法要比较4趟,但是现在只要比较2趟就可以了,这样对于有一定顺序的,可以提高效率。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值