排序 : 1 交换排序

1 交换排序

a 冒泡排序-----稳定

标准的冒泡排序:

ints是一个整型数组

for(int i=0;i<ints.length-1;i++){//比较的轮数,n个数需要比较n-1轮,每一轮冒出一个"泡"

       for(int j=0;j<ints.length-1-i;j++){//每一轮在最后一个位置产生一个最大或最小的数

           if(ints[j]<ints[j+1]){//如果符合条件,两相邻的数交换位置

           int temp;

           temp=ints[j+1];

           ints[j+1]=ints[j];

           ints[j]=temp;

           }

    }

    }

这个算法不好,试想当原来的数已经排好序时,仍然需要比较n-1轮!


改进的冒泡排序:

Boolean swapped;//用于标记是否交换过

    do{

       swapped=false;

       for(int i=0;i<ints.length-1;i++){

           if(ints<ints){

              int temp;

              temp=ints;

              ints=ints;

              ints=temp;

              swapped=true;

           }

       }

    }while(swapped);

因此,改进的冒泡排序最好情况的时间复杂度是O(1).最坏情况需要比较的次数为:1+2+3+...+ n-1=n(n-1)/2,需要移动的次数为:比较次数*3.最坏情况的时间复杂度为O(n的平方).由于两个元素相等就不需要交换,因此此算法是一种稳定的排序算法.不管有多少数,交换时只需temp一个临时变量空间,因此它的空间复杂度为O(1).


b 快速排序----不稳定

快速排序的基本思想
     设当前待排序的无序区为R[low..high],利用分治法可将快速排序的基本思想描述为:
①分解: 
    
 在 R[low..high]中任选一个记录作为基准(Pivot),以此基准将当前无序区划分为左、右两个较小的子区间R[low..pivotpos- 1)和R[pivotpos+1..high],并使左边子区间中所有记录的关键字均小于等于基准记录(不妨记为pivot)的关键字 pivot.key,右边的子区间中所有记录的关键字均大于等于pivot.key,而基准记录pivot则位于正确的位置(pivotpos)上,它无 须参加后续的排序。
  注意:
     划分的关键是要求出基准记录所在的位置pivotpos。划分的结果可以简单地表示为(注意pivot=R[pivotpos]):
     R[low..pivotpos-1].keys≤R[pivotpos].key≤R[pivotpos+1..high].keys
                  其中low≤pivotpos≤high。
②求解: 
     
通过递归调用快速排序对左、右子区间R[low..pivotpos-1]和R[pivotpos+1..high]快速排序。
③组合: 
    
 因为当"求解"步骤中的两个递归调用结束时,其左、右两个子区间已有序。对快速排序而言,"组合"步骤无须做什么,可看作是空操作。

public static void quickSort(int[] a,int low,int high){

  int i,j;

  int temp;//临时存放参考数

  i=low;j=high;

  temp=a[low];

  while(i<j){

     while(i<j&&a[j]>=temp){//在数组的右端扫描,执行完会j会指向比参考数temp小的数

      --j;

     }

     if(i<j){

      a=a[j];//把这个小的数移到参考数的位置

      ++i;//i向后移一位

     }

 

     while(i<j&&a[i]<temp){//在数组的左端扫描,执行完会i会指向比参考数temp大的数

      ++i;

     }

     if(i<j){

      a[j]=a[i];//把这个大的数移到参考数的位置

      --j;//j向前移一位

     }

  }

  a[i]=temp;//一轮结束,把参考数移到它该在的位置

  if(low<i) quickSort(a,low,i-1);//对左端子集合递归

  if(i<high) quickSort(a,j+1,high);//对右端子集合递归

}

快速排序算法是冒泡算法的一个变体.冒泡排序每一轮冒出的那个泡总是在子集的最后一个位置,它把原集合分成一个单分支二叉树,在最坏的情况下,快速排序也是这种情况.但最好的情况下就把原集合分成一个二叉树,它的深度为Ln(n),而轮数是不变的n-1轮(同冒泡),所以时间复杂度变为nLn(n).由于递归需要堆栈空间临时保存调用参数,递归的次数为树的深度,所以空间复杂度为O(Ln(n)),最坏情况下为O(n).两个相邻大小一样的数,后面的有可能跳到前面去,因此此算法不稳定.

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值