冒泡排序算法详解-简单排序算法学习笔记


最近对简单算法进行了一遍复习,对简单排序算法有了更深的理解,闲的有空就整理出来跟大家分享一下。这里先对冒泡排序算法进行分析讨论。

冒泡排序思想

!
冒泡排序算法是通过比较两个相邻元素,然后根据比较条件是否执行交换位置实现的。通常我们会用它来对数组进行排序,下面我将已数组排序作为研究对象对冒泡排序算法进行学习探讨。
假若对一个数组a[]有n个元素,现在对它进行由小到大排序,它的思想是:第一趟在数组(a[0]~a[n-1])(即数组长度-1)中从前往后(根据代码设计有不同区别)进行相邻两个元素的比较。例如第一趟开始时取a[0]与a[1]比较,若a[0]>a[1],则a[0]与a[1]交换位置,否则则不作交换;然后前移一位与下一个元素进行对比,即a[1]和a[2],重复上面比较操作,直到比较完a[n-2]与a[n-1],第一趟比较结束,一共比较了(n-1)次。此时a[n-1]存储了数组中最大的数值,下一趟比较时只需要比较到a[n-2]即可,即比较(n-2)次。重复以上步骤直至最后一趟为n-1趟比较,最后一趟即n-1趟只比较了一次。到此数组a[]已由小到大排序完成。
以上就是冒泡排序的基本思想,从上面分析可以看出,每一趟都需要用一个循环去实现(即内循环),而执行了n-1趟又要用一个循环去包裹(即外循环),即需要使用双重循环(不考虑方法递归情况)来实现冒泡排序算法。而每一趟之间又有相邻元素的比较,即需要用一个条件判断语句放在最里层的循环里面。对于循环语句的使用,我就选择for循环跟大家学习(while循环也差不多),下面我将用java语言对其进行详细的阐述。

冒泡排序算法可执行代码(java)

/**
 * @description 冒泡排序算法深入学习
 * @author Administrator
 * @date 2017/12/5
 */

public class BubbleSort {

    public static void main(String[] args) {

        // 定义一个数组
        int[] a = { 88, 55, 32, 46, 77, 55, 22 };
        // 外循环执行n-1趟,即1开始到a.length-1,length为数组a的长度
        for (int i = 1; i < a.length; i++) {
            // 内循环执行a.length-i次,从数组下标0开始,到a.length - i个下标结束
            for (int j = 0; j < a.length - i; j++) {
                // 相邻两个元素进行判断,如果满足a[j]>a[j+1],则互相交换值
                if (a[j] > a[j + 1]) {
                    /*
                     * 这三句代码基本意思是: 
                     * 创建一个临时的变量temp值存储a[j]; 
                     * 将a[j+1]的值赋给a[j]; 
                     * 将临时变量temp存储的值赋值给a[j+1];
                     * 这样就完成了值交换
                     */
                    int temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }
            }
        }

        // 以上代码执行后冒泡算法就完成了排序操作,数组已经排好序列,下面用for循环遍历输出数组元素
        System.out.println("数组a的冒泡排序结果是:");
        for (int i = 0; i < a.length; i++) {
            // 逐个输出数组a的元素
            System.out.print(a[i] + " ");
        }
        System.out.println();// 换行
    }
}

运行结果是:
这里写图片描述
以上就是我个人写的冒泡排序代码,根据个人喜好不同可能会有风格上的差异,不过基本思想还是不变的。下面我们再在内循环里面写个输出数组的操作,这样就可以跟踪每一趟里面的每一步执行的过程(或者说结果)。添加后的代码如下(以下代码部分注释去掉):

/**
 * @description 冒泡排序算法深入学习
 * @author Administrator
 * @date 2017/12/5
 */

public class BubbleSort {

    public static void main(String[] args) {

        // 定义一个数组
        int[] a = { 88, 55, 32, 46, 77, 55, 22 };
        // 外循环执行n-1趟,即1开始到a.length-1,length为数组a的长度
        for (int i = 1; i < a.length; i++) {
            // 内循环执行a.length-i次,从数组下标0开始,到a.length-i个下标结束
            for (int j = 0; j < a.length - i; j++) {
                // 相邻两个元素进行判断,如果满足a[j]>a[j+1],则互相交换值
                if (a[j] > a[j + 1]) {                  
                    int temp = a[j];
                    a[j] = a[j + 1];
                    a[j + 1] = temp;
                }

                System.out.println("第" + i+ "轮第" + (j + 1) + "次的排序结果为:");
                for (int k = 0; k < a.length; k++) {
                    // 逐个输出数组a的元素
                    System.out.print(a[k] + " ");
                }
                System.out.println("\n");// 输出后换行(2行)
            }
        }

        // 以上代码执行后冒泡算法就完成了排序操作,数组已经排好序列,下面用for循环遍历输出数组元素
        System.out.println("数组a的冒泡排序结果是:");
        for (int i = 0; i < a.length; i++) {
            // 逐个输出数组a的元素
            System.out.print(a[i] + " ");
        }
        System.out.println();// 换行
    }
}

运行结果部分截图:
添加代码后每一趟每一步的执行结果

添加代码后每一趟每一步的执行结果
以上输出的结果就是每一趟中的每一步执行的结果。
如果对以上代码进行debug进行断点调试,那么可以清晰的了解到每一步都进行了什么样的操作:
debug模式下的比较输出

从图中我们可以看出数组中a[0]和a[1]的值在比较后已经互相交换值,而其它元素的值则还没改变。

个人总结

!
从以上看,其它书写方式也大体相同,不过使用时需要注意的是for循环次数限制值,即在数组下标没有越界的情况下要遍历完所需要比较的所有元素。不难发现冒泡排序算法在排序的过程中,只要有相邻元素对比较都要继续执行下去,如上面运行结果中第6趟只进行了一次对比比较。不过以上说法是按照一般情况下来说的,假如序列刚开始就是按照预定排序排好的,那么只需要进行一趟比较排序即可,即(n-1)次比较,所以最好情况下的时间复杂度是O(n),无需移动元素,不过对于循环来说,还是要进行n(n-1)/2次比较的。最坏的情况进行(n-1)遍,即和循环次数相同,移动元素的次数为3n(n-1)/2,因此最坏情况下的时间复杂度为O(n^2)。
经过以上分析可知,该算法执行时间与元素的初始排列有关,冒泡排序经过一趟排序后能确定一个元素的最终位置。
如果对简单排序算法比较了解的同学可以发现,冒泡排序与简单选择排序差不多,但是冒泡排序中移动的元素次数明显比简单选择排序多,因为冒泡排序是相邻2个元素之间进行比较,而简单选择排序是取出一个元素与余下未排好序的元素进行比较。此外,冒泡排序是稳定的排序方法(对于同一个序列排序,多次排序所化的时间差距不大)。
(下面附上简单排序算法的关键代码,有关于其它算法的学习以后有时间在跟大家分享。)
(由于冒泡排序算法实现比较容易,代码和排序思想理解大同小异。如果有与大家有雷同的地方请谅解。)

//选择排序算法关键部分代码
//外循环从第一个元素开始每次取出一个与余下的(内循环)互相比较
for(int i=0;i<a.length;i++){
    //余下的未比较元素
    for(int j=i+1;j<a.length;j++){
        if(a[i]>a[j]){//每次取出的元素与余下的互相比较
            int temp=a[i];
            a[i]=a[j];
            a[j]=temp;
        }
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值