其他分享
首页 > 其他分享> > 必须知道的冒泡排序

必须知道的冒泡排序

作者:互联网

了解一下冒泡排序是什么,冒泡排序跟快排一样都是交换排序,n个元素中通过每次遍历比较j 与 j+1下标数据比较,如果不符合排序规则进行交换,进行n次来回,每次来回从头开始比较。就是两两相互比较,然后考虑是否交换。当然,这里也有很多重复的操作,接下来会慢慢优化。

当然不可避免的是冒泡排序时间复杂度为n的平方是没的跑的,不过也可以消除重复操作优化代码。

下面给出一个不需要考虑任何细节的冒泡排序,就像上述介绍冒泡排序的一样,我们就从头到n以此前后两两比较,来回走n次,如果不符合排序规则交换两个数。


public class BubbleSortTest {
	
	public static void main(String[]args) {
		int data[] = {
				8,3,4,5,1,2,6,7,9
		};
		for(int i=0;i<data.length;i++) {  //冒泡排序开始
			
			for(int j = 1;j< data.length;j++) {
				
				if(data[j]<data[j-1]) {  //两两进行比较 不符合则交换
				
					int temp = data[j];
					data[j] = data[j-1];
					data[j-1] = temp;
				}
			}
			
		}
		
		for(int d: data) {
			System.out.print(d+" ");
		}
	
	}
}

当然,上述的冒泡算法也可以改成这样,就是要控制好下标会不会越界的问题。

	for(int i=0;i<data.length;i++) {
            
            for(int j = 0;j< data.length-1;j++) {
				
				if(data[j+1]<data[j]) {
				
					int temp = data[j+1];
					data[j+1] = data[j];
					data[j] = temp;
				}
			}
			
		}

上述的冒泡非常的简单明了,如果真的写不出来,就用上面也可,但是排序出来的数据速度有点慢。

下面将进行冒泡排序的特点进行一些优化。排序规则为递增排列。length为整个数组的长度。

1.考虑到每次是从 下标 i = 0 与 i+1 开始进行两两比较,如果i+1的值比i 的值要小,那么它们就会进行交换,那么进行到了 i = length-2的比较之后,我们就会发现第一次从头遍历排序之后,我们找到了一个最大的值,并且这个最大的值放在了length-1下标上。

也就是说,第一次从头遍历,我们找到了整个数组的最大值并且将其数值放到了length-1下标中,那就是每次从头遍历都会找到一个“最大值”,并且放在了对的地方。

那么,我们下一次从头遍历,就不需要在比较length-1 ,那么后面每次从头遍历都会增加一个不需要比较的,我们就可以控制内循环的下标比较的结束条件,根据外循环初始为i=0或者=1的时候,进行内循环结束条件的限制改成 j<data.length-1-i(当i=0开始),j<data.length-1-i+1(当i=1开始) ,第一次从头遍历之后才出现了一个当前比较的最大值,所以通过i的初始变化,我们也可以适当改变j的结束条件。

另外外循环是必须要遍历length次的。因为每次从头遍历只选出了1个当前最大值,我们要寻找length个。

public class BubbleSortTest {
	
	public static void main(String[]args) {
		int data[] = {
				8,3,4,5,1,2,6,7,9
		};
		for(int i=0;i<data.length;i++) {
			
			for(int j = 0;j< data.length-1-i;j++) { //改变了内循环的结束条件。
				
				if(data[j+1]<data[j]) {
				
					int temp = data[j+1];
					data[j+1] = data[j];
					data[j] = temp;
				}
			}
			
		}
		
		for(int d: data) {
			System.out.print(d+" ");
		}
	
	}
}

另外一个就是假如要外循环从1开始,只需要在内循环j的结束条件上+1就行。

for(int i=1;i<=data.length;i++) {
			
			for(int j = 0;j< data.length-1-i+1;j++) {
				
				if(data[j+1]<data[j]) {
					int temp = data[j+1];
					data[j+1] = data[j];
					data[j] = temp;
				}
			}
}
		

2.另外,发现了很多特殊情况,我们的外循环需要遍历length次,假如我们的数据在length遍历前就已经排序成功了,我们是不是需要提前结束排序?

数据本身就是递增排序的,我们通过冒泡排序也是求出该数组的递增序列,这个时候就发现不需要让程序跑这么多次,那如何检测在没有外循环全部遍历完数组就已经排序完成了呢 ? 后面发现一次从头遍历完如果数组还没有完全递增序列的话就会进行交换操作。反之,从头遍历完发现没有一次进行交换的操作,就可以认定为当前数组元素排列已经递增了,不需要在进行比较遍历了。

public class BubbleSortTest {
	
	public static void main(String[]args) {
		int data[] = {
				8,3,4,5,1,2,6,7,9
		};
		for(int i=1;i<=data.length;i++) {
			boolean status = false; //初始化为false没有交换了
			for(int j = 0;j< data.length-1-i+1;j++) {
				
				if(data[j+1]<data[j]) {
					status = true;  //为true表示仍然要交换
					int temp = data[j+1];
					data[j+1] = data[j];
					data[j] = temp;
				}
			}
            //从头遍历完之后判断
			if(status == false) { //没有交换了就跳出所有循环。
				break ;
			}
		}
		
		for(int d: data) {
			System.out.print(d+" ");
		}
	
	}
}

冒泡排序的优化有两点:

1.重复数据的比较 (减少重复比较的数据)

2.重复遍历的次数(早点停止循环)

冒泡排序的交换思想也被用到了快排中,快排是对其排序算法时间复杂度提升到了一个层次的排序算法,为学习快排打下了基础。

标签:遍历,int,冒泡排序,length,必须,排序,从头,知道
来源: https://blog.csdn.net/wasane/article/details/117933442