[排序算法]--冒泡排序的多种实现(Java)

冒泡排序

定义
冒泡排序是一种简单的排序算法。它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。

算法描述

比较相邻的元素。如果第一个比第二个大,就交换它们两个;
对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对,这样在最后的元素应该会是最大的数; 针对所有的元素重复以上的步骤,除了最后一个;
重复步骤1~3,直到排序完成。

思路:消除相互紧邻的逆序的元素
方法:扫描交换
不变性:经过k轮扫描交换后,最大的k个元素必然就位
单调性:经k轮扫描交换后,问题规模缩减至n-k
正确性:经至多n趟扫描交换后,算法必然终止,且能给出正确答案

注:参数列表为(int a[], int n)是自己写的
以上就是冒泡排序的基本思想,按照这个定义很快就能写出代码:
在这里插入图片描述

 //无优化
    //冒泡排序的本质是通过两两比较将大数往后移动,每一趟迭代后将最大值、次大值...分别放到正确的位置
    **public static void bubbleSort(int a[], int n) {
        for (int i=n; i>0; i--) {
            for (int j=1;j<n;j++) {//遍历n次
                if (a[j] < a[j-1]) {
                    int temp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = temp;
                }
            }
        }
    }**

改进1:
在这里插入图片描述
在这里插入图片描述
n* 根号n n是遍历数量,根号n是迭代趟数
依次比较每一对相邻元素,如有逆序,交换之;若整趟扫描都没有交换,则排序完成;否则再做一趟扫描交换
方法1(不易懂):
sorted = !sorted; 在下一趟扫描之前进行翻转,初始化为true
退出条件:翻转之前是true。(那上一次内层循环必然没有进行交换)

public class Sort {
    public static void bubbleSort1(int A[], int n) {
        //逐趟扫描交换,直至完全有序(一趟一趟的扫描交换)
        for (boolean sorted = false; sorted = !sorted; n--) {//执行扫描交换
            //内层:每次循环需要两两比较的次数,每次比较后,都会将当前最大的数放到最后位置,所以每次比较次数递减一次
            for (int j = 1; j<n; j++ ) {
                if (A[j-1] > A[j]) {
                    //若逆序看,交换数组array的j和j+1位置的数据
                    int temp = A[j-1];
                    A[j-1] = A[j];
                    A[j] = temp;
                    sorted = false;//清楚全局有序标志
                }
            }
        }
    }

    public static void main(String[] args) {
        int A[] = {5,3,6,9,88,12,89};
        bubbleSort1(A, 3);
        for (int a : A) {
            System.out.println(a);
        }
    }
}

问题:该算法必然会结束,至多迭代多少趟?
不变性:经过k轮扫描交换后,最大定位k个元素必然就位
单调性:经过k轮扫描交换后,问题规模缩减至n-k
正确性:经至多n趟扫描后,算法必然终止,且能给出正确答案

方法二(容易理解):迭代进行low,high–之间的所有相邻元素,只要有一对相邻元素逆序,就进行交换
每一趟对bubble调用所需要时间都正比于前n-k个元素的长度。

public class Sort {
    public static void bubbleSort2(int A[], int n) {
        //逐趟扫描交换,直至完全有序
        while (!bubble(A, 0, n--));
    }

    static boolean bubble(int A[], int low, int high) {
        boolean sorted = true;//有序推论
        while (++low < high) {
            if (A[low-1] > A[low]) {
                //若逆序看,交换数组array的j和j+1位置的数据
                int temp = A[low-1];
                A[low-1] = A[low];
                A[low] = temp;
                sorted = false;//清楚全局有序标志
            }
        }
        return sorted;
    }

    public static void main(String[] args) {
        int A[] = {5,3,6,9,88,12,89};
        bubbleSort2(A, 7);
        for (int a : A) {
            System.out.println(a);
        }
    }
}

方法三:

 public static void bubbleSort3(int a[], int n) {
        int i = n;
        boolean sorted = false;
        while (!sorted) {//无序
            sorted = true;
            for (int j=1;j<n;j++) {//遍历n次
                if (a[j] < a[j-1]) {
                    int temp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = temp;
                    sorted = false;
                }
            }
            i--;
        }
    }

改进2:
在这里插入图片描述
进一步做优化。比如,现在有一个包含1000个数的数组,仅前面100个无序,后面900个都已排好序且都大于前面100个数字,那么在第一趟遍历后,最后发生交换的位置必定小于100,且这个位置之后的数据必定已经有序了,也就是这个位置以后的数据不需要再排序了,于是记录下这位置,第二次只要从数组头部遍历到这个位置就可以了。如果是对于上面的冒泡排序算法改进1来说,虽然也只排序100次,但是前面的100次排序每次都要对后面的900个数据进行比较,而对于现在的排序算法改进2,只需要有一次比较后面的900个数据,之后就会设置尾边界,保证后面的900个数据不再被排序。

 public static void bubbleSort3(int a[], int n) {
        int last = n;
        while (last > 0) {
           last = 0;
            for (int j = 1; j< n; j++) {
                if (a[j] < a[j-1]) {
                    int temp = a[j];
                    a[j] = a[j-1];
                    a[j-1] = temp;
                    last = j;
                }
            }
        }
    }
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值