冒泡排序

一、什么是冒泡排序

   冒泡排序的思想: 比较相邻两个数,把大的数放在右边(也可以把小的数放在右边,看排序规则,这里按从小到大排序进行说明)。所以,当第一趟排序结束后(比较了n - 1次,n为数组元素个数),最大的数就到了最后面,其余的数还是处于无序状态;接着进行第二趟排序(比较了n - 2次),把第二大的数放到倒数第二位;依次类推:每一趟排序比较的次数减1,一共比较n - 1趟,排序结束。如下图所示:

举例说明,要排序数组为:{6,3,8,2,9,1},过程如下(按从小到大排列):

第一趟排序:

    第一次排序:6和3比较,6大于3,交换位置:    3  6  8  2  9  1

    第二次排序:6和8比较,6小于8,不交换位置: 3  6  8  2  9  1

    第三次排序:8和2比较,8大于2,交换位置:    3  6  2  8  9  1

    第四次排序:8和9比较,8小于9,不交换位置:3  6  2  8  9  1

    第五次排序:9和1比较:9大于1,交换位置:   3  6  2  8  1  9

    第一趟总共进行了5次比较, 排序结果:            3  6  2  8  1  9

---------------------------------------------------------------------------------------------------------------

第二趟排序:

    第一次排序:3和6比较,3小于6,不交换位置:3  6  2  8  1  9

    第二次排序:6和2比较,6大于2,交换位置:   3  2  6  8  1  9

    第三次排序:6和8比较,6大于8,不交换位置:3  2  6  8  1  9

    第四次排序:8和1比较,8大于1,交换位置:   3  2  6  1  8  9

    第二趟总共进行了4次比较, 排序结果:            3  2  6  1  8  9

---------------------------------------------------------------------------------------------------------------

第三趟排序:

    第一次排序:3和2比较,3大于2,交换位置:    2  3  6  1  8  9

    第二次排序:3和6比较,3小于6,不交换位置:2  3  6  1  8  9

    第三次排序:6和1比较,6大于1,交换位置:   2  3  1  6  8  9

    第三趟总共进行了3次比较, 排序结果:            2  3  1  6  8  9

---------------------------------------------------------------------------------------------------------------

第四趟排序:

    第一次排序:2和3比较,2小于3,不交换位置: 2  3  1  6  8  9

    第二次排序:3和1比较,3大于1,交换位置:    2  1  3  6  8  9

    第四趟总共进行了2次比较, 排序结果:             2  1  3  6  8  9

---------------------------------------------------------------------------------------------------------------

第五趟排序:

    第一次排序:2和1比较,2大于1,交换位置:  1  2  3  6  8  9

    第五趟总共进行了1次比较, 排序结果:           1  2  3  6  8  9

---------------------------------------------------------------------------------------------------------------

最终结果:1  2  3  6  8  9

由此可见,冒泡排序可以用双重循环实现,外层循环控制排序趟数,内层循环控制比较次数

二、代码实现

import java.util.ArrayList;
import java.util.List;
import java.util.Scanner;

public class BubbleSort {

	public static void main(String[] args) {
        Scanner sc = new Scanner(System.in);
        int len = sc.nextInt();
        List<Integer> array = new ArrayList<Integer>();
        for(int i = 0;i < len;i++) {
        	int element = sc.nextInt();
        	array.add(element);
        }
        bubbleSort(array);
        print(array);
        sc.close();
	}

	/**
	 * 
	 * @param array 待排序序列
	 */
	public static void bubbleSort(List<Integer> array) {
		for(int i = 1;i < array.size();i++) {
			for(int j = 0;j < array.size() - i;j++) {
				if(array.get(j) > array.get(j + 1)) {
					int temp = array.get(j);
					array.set(j, array.get(j + 1));
					array.set(j + 1, temp);
				}
			}
		}
	}
	
	public static void print(List<Integer> array) {
		for(int item : array) {
			System.out.print(item + " ");
		}
	}
}

三、冒泡排序的时间复杂度分析

    显然,不管待排序的序列是否有序,上述的冒泡排序代码的时间复杂度都是O(n²),而且排序的算法是稳定的。所以我们可以对冒泡排序的算法进行优化,使得序列有序时,退出循环。

四、冒泡排序原始算法优化

优化思想:

当我们检测到还没有排序的序列有一部分是有序的时候,我们不对有序的那部分序列进行遍历,这样能大大减少比较次数。即:可以设置一个指针指向每次发生数据交换的位置,每一趟排序的最大边界就为这个位置(即这个位置以后的数据都是有序的,不再进行判断),这样会大大减少比较的次数。

举例说明,要排序数组为:{6,1,3,2,4,5},指针 index = len - 1 = 5(循环之外初始化的值),过程如下(按从小到大排列):

第一趟排序:

    第一次排序:6和1比较,6大于1,交换位置:    1  6  3  2  4  5        index = 0

    第二次排序:6和3比较,6大于3,交换位置:    1  3  6  2  4  5        index = 1

    第三次排序:6和2比较,6大于2,交换位置:    1  3  2  6  4  5        index = 2

    第四次排序:6和4比较,6大于4,交换位置:    1  3  2  4  6  5        index = 3

    第五次排序:6和5比较:6大于5,交换位置:    1  3  2  4  5  6        index = 4

    第一趟总共进行了5次比较, 排序结果:             1  3  2  4  5  6

---------------------------------------------------------------------------------------------------------------

每一趟排序开始的时候指针会初始化为0

第二趟排序:(内存循环的边界为4)

    第一次排序:1和3比较,1小于3,不交换位置:    1  3  2  4  5  6       index = 0

    第二次排序:3和2比较,3大于2,交换位置:        1  2  3  4  5  6       index = 1

    第三次排序:3和4比较,3小于4,不交换位置:    1  2  3  4  5  6        index = 1

              第四次排序:4和5比较,4小于5,不交换位置:    1  2  3  4  5  6        index = 1

    第一趟总共进行了4次比较, 排序结果:            1  2  3  4  5  6   

---------------------------------------------------------------------------------------------------------------

第三趟排序:(指针初始化为0,内存循环的边界为1,所以只进行一次比较)

    第一次排序:1和2比较,1小于2,不交换位置:    1  2  3  4  5  6       index = 0

    第一趟总共进行了1次比较, 排序结果:            1  2  3  4  5  6   

---------------------------------------------------------------------------------------------------------------

从第三趟排序后可知:内层循环边界为0,表示序列全部有序,排序结束

五、优化后的代码

public static void bubbleSort_Optimizer(List<Integer> array) {
		int index = array.size();
		int len = index - 1;
		while(index > 0) {
			index = 0;
			for(int i = 0; i < len;i++) {
				if(array.get(i) > array.get(i + 1)) {
					int temp = array.get(i);
					array.set(i, array.get(i + 1));
					array.set(i + 1, temp);
					index = i;
				}
			}
			len = index;
		}
	}

六、优化后的算法时间复杂度分析

     从优化后的代码可知:当待排序序列为一个有序序列时,整个排序算法只执行了一次外层while循环和一次内层for循环,比较了n - 1,然后就会退出双重循环,排序结束,这是最好的情况,时间复杂度为O(n);反之,最坏的情况为O(n²),并且改进后的冒泡排序算法仍然是稳定的

  • 2
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值