冒泡排序

  冒泡排序:以从小到大排序为例,就是每一轮排序将数组中最大的值放到数据的最后。

  设数组的长度为n:

  1、比较前后两个相邻的数据,如果前面的比后面的大,就交换两个数据的位置。

  2、这样对数组的第0个数据到第N-1个数据进行遍历后,该数组中最大的值就被放到了数组的第N-1个位置上(也就是数组的末尾)

  以上就是冒泡排序的基本思想,根据上面的思路很快就可以写出冒泡排序的代码。

/**
 * 冒泡排序的第一种实现, 没有任何优化
 * @param a
 * @param n
 */
public static void bubbleSort1(int [] a, int n){
    int i, j;

    for(i=0; i<n; i++){//表示n次排序过程。
        for(j=1; j<n-i; j++){
            if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
                //交换a[j-1]和a[j]
                int temp;
                temp = a[j-1];
                a[j-1] = a[j];
                a[j]=temp;
            }
        }
    }
}// end
给出一个测试代码:
public static void main(String[] args) {
    int[] arr = {1,1,2,0,9,3,12,7,8,3,4,65,22};

    BubbleSort.bubbleSort1(arr, arr.length);

    for(int i:arr){
        System.out.print(i+",");
    }
}
运行结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
 
下面开始考虑优化的问题,如果对于一个本身有序的序列,或者序列后面一大部分都是有序的序列,上面的算法就会浪费很多的时间开销,
这里设置一个flag,如果发生了交换,就设置为true,否则为false。明显如果一趟没有发生交换,就说明排序已经完成。
public static void bubbleSort2(int [] a, int n){
    int j, k = n;
    boolean flag = true;//发生了交换就为true, 没发生就为false,第一次判断时必须标志位true。
    while (flag){
        flag=false;//每次开始排序前,都设置flag为未排序过
        for(j=1; j<k; j++){
            if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
                //交换a[j-1]和a[j]
                int temp;
                temp = a[j-1];
                a[j-1] = a[j];
                a[j]=temp;

                //表示交换过数据;
                flag = true;
            }
        }
        k--;//减小一次排序的尾边界
    }//end while
}//end
运行测试main函数结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
 
 
进一步优化:比如现在有包含1000个数的数组,仅前面100个数无序,后面的900个数有序并且全部大于前面的100个数,
那么在第一趟遍历后,最后发生交换的位置必定小于100,且这个位置之后的数据必定有序了,也就是说这个位置之后的
数据不需要再排序了,于是记录下这个位置,第二次只要从数组的头部遍历到这个位置即可。如果是对于上面的冒泡排序2
的算法来说,虽然也只排序100次,但是前面的100次排序都要对后面900个数进行比较,而对于现在的排序算法3,只需要有
一次比较后面的900个数据,之后就会设置尾边界,保证对后面900个数据不进行排序。
public static void bubbleSort3(int [] a, int n){
    int j , k;
    int flag = n ;//flag来记录最后交换的位置,也就是排序的尾边界

    while (flag > 0){//排序未结束标志
        k = flag; //k 来记录遍历的尾边界
        flag = 0;

        for(j=1; j<k; j++){
            if(a[j-1] > a[j]){//前面的数字大于后面的数字就交换
                //交换a[j-1]和a[j]
                int temp;
                temp = a[j-1];
                a[j-1] = a[j];
                a[j]=temp;

                //表示交换过数据;
                flag = j;//记录最新的尾边界.
            }
        }
    }
}
这种方法是我看到的最优化的冒泡排序了。 
运行测试例子结果:
0,1,1,2,3,3,4,7,8,9,12,22,65,
 
可知运行结果正确。

 

posted @ 2018-10-02 18:36  有个八块腹肌的梦想  阅读(244)  评论(0编辑  收藏  举报