• 排序算法—冒泡排序


    排序算法—冒泡排序

    排序算法—冒泡排序

    1 问题描述

    引子

    排序是数据结构中十分重要的一章,排序算法有很多种,一直没时间整理而且很多排序算法理解的也不是很透彻.希望通过这次整理吃透吧! 排序算法十分多,故分篇进行整理.

    说明

    本文重点是理解排序算法,而不是完整的程序,所以每节都只有具体排序算法的接口.没有完整的源代码.

    分类
    内部排序
    整个排序过程完全在内存中进行.
    外部排序
    因为待排序的记录数据太大,内存无法容纳全部数据,需要借助外部存储设备才能完成排序.

    2 冒泡排序(Bubble)

    这个应该是众多程序员接触的第一个排序算法,十分基础.

    冒泡排序算法的原理如下:

    每次比较相邻的元素,如果第一个数比第二个数大,就交换他们.对每一对相邻元素做同样的工作,

    从开始第一对到最后一对.这步做完后,最后的元素就是最大的数.重复上述步骤,这样第 i 次比较完后,

    最后的元素就是第 i 大的数.持续每次对越来越少的元素重复上面的步骤,直到没有需要比较的元素为止.

    2.1 冒泡排序(一)

     1:  /**
     2:    * 基本的冒泡排序
     3:    * @param int* num 排序数组
     4:    * @param int length 数组大小
     5:    * @return int 排序成功与否
     6:    */
     7:  int BubbleSort(int *num, int length)
     8:  {
     9:     int i,j;
    10:     if(length < 2)
    11:        return 0;
    12:     for(i = 0; i < n; i++)           //外层循环控制排序的趟数
    13:     {
    14:        for(j = 0; j < n-1-i; j++)    //内层循环控制排序要交换的数的范围
    15:        {
    16:           if(num[j] > num[j+1])
    17:              swap(num[j],num[j+1])   //两两相邻的数比较大小 
    18:        }
    19:     }
    20:     return 0;
    21:  }
    22:  算法分析:
    23:    时间复杂度:最优的情况,所有的数都是有序的,那么内层循环就不用交换数了,
    24:                      只进行外层的循环,复杂度是O(n);
    25:             最差的情况,所有的数都是倒序的,那么两层循环都要进行,复杂度是O(n^2);
    26:             平均时间复杂度是O(n^2);
    27:      空间复杂度:一维数组 O(1);
    

    该思路也可以逆序进行,伪代码如下:

     1:  for(i from n-1 downto 0)
     2:  {
     3:     for(j from n-1 downto n-1-i)
     4:     {
     5:        cmp(num[j],num[j-1])
     6:     }
     7:  }
     8:  
     9:  // 其他类似的写法还有:
    10:  for(i = n-1; i > 0; i--)
    11:  {
    12:     for(j = 0; j > i; j++)
    13:     {
    14:        cmp(j,j+1)
    15:     }
    16:  }
    17:  
    18:  // 交换排序
    19:  for(i = 0; i < n-1; i++)
    20:  {
    21:     for(j = i+1; j < n; j++)
    22:     {
    23:        cmp(num[i],num[j])   //此时比较的不是相邻的两个元素了
    24:     }
    25:  }
    

    2.2 冒泡排序(二)

    上述的排序是两两相邻的数进行比较,更符合冒泡的形态.但实际上要比较的也不一定就是相邻的数.

     1:    /**
     2:    * 改进的冒泡排序一
     3:    * @param int* num 排序数组
     4:    * @param int length 数组大小
     5:    * @return int 排序成功与否
     6:    */
     7:   
     8:  //逆序版 但还是不同的较少了交换的次数 而且类似选择排序
     9:  int BubbleSort(int *num, int length)
    10:  {
    11:     int i,j,max;
    12:     if(length < 2)
    13:        return 0;
    14:     for(i = n-1; i > 0; i--)           //外层循环控制排序的趟数
    15:     {
    16:        for(j = 1,max = 0; j < i; j++)  //从0~j左边部分选出最大的数
    17:        {
    18:           if(num[max] < num[j])
    19:             max = j;
    20:        }
    21:        if(num[i] < num[max])
    22:          swap(num[i],num[max]);
    23:     }
    24:     return 0;
    25:  }
    

    2.3 冒泡排序(三)

    可以设置一个标志,如果一趟过程中发成了交换,则为true,反之则未false,如果有一趟没有发生交换就说明排序已经完成

     1:  /**
     2:    * 改进的冒泡排序二
     3:    * @param int* num 排序数组
     4:    * @param int length 数组大小
     5:    * @return int 排序成功与否
     6:    */
     7:  int BubbleSort(int *num, int length)
     8:  {
     9:     int i,j,flag;
    10:     if(length < 2)
    11:        return 0;
    12:     for(i = 0; i < n-1; i++)       //外层循环控制排序的趟数
    13:     {
    14:        flag = 0;
    15:        for(j = n-1; j > i; i++)    //内层循环控制依次排序的完成
    16:        {
    17:           if(num[j] > num[j-1])
    18:           { 
    19:             swap(num[i],num[j])  
    20:             flag = 1;
    21:           }
    22:        }
    23:        if(flag == 0)               //终止排序
    24:          break;     
    25:     }
    26:        return 0;
    27:  }  
    28:  如果100个数,就前10个数是乱序的,后面的数是有序的.可以通过设置标志记录交换时的位置,下一次循环到此处即可.
    29:  int BubbleSort(int *num, int length)
    30:  {
    31:     int i,j,lastchange;            //lastchange记录上次交换的位置
    32:     if(length < 2)
    33:        return 0;
    34:     i = n;
    35:     while(i > 0)
    36:     {
    37:       lastchange = 0;
    38:       for(j = 0; j < i; j++)
    39:       {
    40:          if(num[j] > num[j+1])
    41:          {
    42:             swap(num[j],num[j+1])
    43:             lastchagne = j;
    44:          } //if
    45:       }// for
    46:       i = lastchange;
    47:     }
    48:        return 0;
    49:  }  
    

    2.4 冒泡排序(四)

    双向冒泡进一步提高效率,又称鸡尾酒排序.

     1:   /**
     2:  * 基本的冒泡排序
     3:  * @param int* num 排序数组
     4:  * @param int length 数组大小
     5:  * @return int 排序成功与否
     6:  */
     7:  int BubbleSort(int *num, int length)
     8:  {
     9:     int i,j,left,right,l,r;
    10:     left = 0;i = 0;
    11:     right = length-1;
    12:     
    13:     //双向冒泡
    14:     while(left < right)
    15:     {
    16:     //必须要给l和r赋值,否则若数组一开始就是有序,则right = r时,r未赋值会报错.
    17:       l = left + 1;
    18:       r = right - 1;
    19:       
    20:       // 第一次循环将最大的值放到末尾
    21:       for(j = left; j < right; j++)
    22:       {
    23:          if(a[j] > a[j+1])
    24:          { 
    25:             swap(a[j],a[j+1]);
    26:             r = j;
    27:          }
    28:       }
    29:       right = r;  // 这里好好想想,r 不一定是最后一个数喔!
    30:      
    31:      //第二次循环将最小的值放到开头
    32:       for(j = right; j > left; j--)
    33:       { 
    34:         if(a[j] < a[j-1])
    35:         {
    36:            swap(a[j],a[j-1]);
    37:            l = j;
    38:         }
    39:       }
    40:       left = l;
    41:       
    42:       //测试结果
    43:       /*
    44:        printf("第%d次排序结果:",i+1);
    45:        i++;
    46:        for(j = 0; j < n; j++)
    47:         printf("%d	",a[j]);
    48:       */
    49:     }
    50:  }
    51:     
    

    Date: 2014-08-15 Fri

    Author: Chen Jingran

    Org version 7.8.11 with Emacs version 24

    Validate XHTML 1.0
  • 相关阅读:
    spring事务
    事务理解
    zookeeper总结
    maven项目怎样将本地jar包打进去
    applicationcontext理解使用
    servlet 中getLastModified()
    Findbug插件静态java代码扫描工具使用
    上行短信/下行短信
    zookeeper基本原理
    git分支的合并
  • 原文地址:https://www.cnblogs.com/programmer-cjr/p/3920433.html
Copyright © 2020-2023  润新知