快速排序分析
2017-11-14 23:35
148 查看
前言:
刚刚学习到快速排序,快速排序是个基础问题,去网上查了下,发现竟然没有一个让人满意的答案。
就连为什么快速排序比冒泡排序快这个基本的概念,也没人说清楚。
一般而言,网上对于为什么快速排序比冒泡快,有两种方向:
1.算时间复杂度
2.二分法的优越性
对于这两种解释,明显没有从根本上触及原理。
对于1.算时间复杂度
这是逻辑颠倒,恰恰是效率高导致时间复杂度低。所以说这种解释因果倒置。
对于2.二分法的优越性
这个我不知道说什么好。
这里预先我给出我的答案:冒泡法一轮比较,只确定了一个数的位置。而快速排序,可以确定一个点的同时,还将数组一分为二。冒泡排序由于是不同的数相比较而快速排序是和相同的数比较。相当于在比较中选择了最极端的模式,浪费了信息。冒泡排序可以算是每次都是最坏选择的快速排序。(实际操作中:为提高效率,快速排序一般是一分为二,而没有确定一个点的位置)
概念:
快速排序:对一个数组操作,将数组分成两部分,前面的一部分比后面的一部分小(同组之间乱序),然后继续分割两个小数组。。。
将数组分成两部分的操作:选取数组中的一个数,从两端开始比较,左端的话如果小于就说明这个数可以放左边,比较下一个,如果大于那么先待定;右边的话,如果大于基数那么说明这个数可以放右边,比较下一个,如果小于那么和刚刚那个数对换。这样依次确认位置,就能划分完整个数组。
如何通过比较和交换位置,达到左边的都比该数小,右边的都比该数大.
这里直接给出思路:
1.单边确认
规定:需要排序的数组为arr ,选取的第一个排序数为:arr[random](r表示在数组下标范围之内的随机数)
1.if(arr[0]>arr[random]){arr[0]和arr[length-1]交换位置(此操作等于确定了数组最后一个位置的值)}
2.if(arr[0]<arr[r]){比较下一个(此操作等于确定了数组第一个位置的值)}
基于以上思路,给出代码:
此时我们发现:有很多交换操作是不必要的,例如:如果最后一个数是大于基数的就没必要换过来。以及对于等于的情况没有处理,所以无法排序有等值的数列。
2.双边排序+等值处理
刚刚学习到快速排序,快速排序是个基础问题,去网上查了下,发现竟然没有一个让人满意的答案。
就连为什么快速排序比冒泡排序快这个基本的概念,也没人说清楚。
一般而言,网上对于为什么快速排序比冒泡快,有两种方向:
1.算时间复杂度
2.二分法的优越性
对于这两种解释,明显没有从根本上触及原理。
对于1.算时间复杂度
这是逻辑颠倒,恰恰是效率高导致时间复杂度低。所以说这种解释因果倒置。
对于2.二分法的优越性
这个我不知道说什么好。
这里预先我给出我的答案:冒泡法一轮比较,只确定了一个数的位置。而快速排序,可以确定一个点的同时,还将数组一分为二。冒泡排序由于是不同的数相比较而快速排序是和相同的数比较。相当于在比较中选择了最极端的模式,浪费了信息。冒泡排序可以算是每次都是最坏选择的快速排序。(实际操作中:为提高效率,快速排序一般是一分为二,而没有确定一个点的位置)
概念:
快速排序:对一个数组操作,将数组分成两部分,前面的一部分比后面的一部分小(同组之间乱序),然后继续分割两个小数组。。。
将数组分成两部分的操作:选取数组中的一个数,从两端开始比较,左端的话如果小于就说明这个数可以放左边,比较下一个,如果大于那么先待定;右边的话,如果大于基数那么说明这个数可以放右边,比较下一个,如果小于那么和刚刚那个数对换。这样依次确认位置,就能划分完整个数组。
如何通过比较和交换位置,达到左边的都比该数小,右边的都比该数大.
这里直接给出思路:
1.单边确认
规定:需要排序的数组为arr ,选取的第一个排序数为:arr[random](r表示在数组下标范围之内的随机数)
1.if(arr[0]>arr[random]){arr[0]和arr[length-1]交换位置(此操作等于确定了数组最后一个位置的值)}
2.if(arr[0]<arr[r]){比较下一个(此操作等于确定了数组第一个位置的值)}
基于以上思路,给出代码:
public static void sort(int[] arr,int left,int right) { //设置递归结束条件 if (right-left<1) { return ; } int l=left; int r=right; int sPoint=arr[left+new Random().nextInt(right-left+1)];//用随机位置确定比较的基数 while (l<=r) {//使用等于为了比较每一个数 if (arr[l]<=sPoint) { l++;//这里就确定了一个左边位置 }else if(arr[l]>sPoint){ int temp=arr[r]; arr[r]=arr[l]; arr[l]=temp; r--; //这里是一个交换操作,不过用往后抛形容更恰当,因为这样操作一次,右边的位置就确定了一个 } } if (l-1>=0) { sort(arr, left,l-1); } sort(arr, r+1, right); }
此时我们发现:有很多交换操作是不必要的,例如:如果最后一个数是大于基数的就没必要换过来。以及对于等于的情况没有处理,所以无法排序有等值的数列。
2.双边排序+等值处理
public static void sort2(int[] arr,int left,int right) { if (right-left<1) { return ; } int l=left; int r=right; int index=left+new Random().nextInt(right-left+1); int sPoint=arr[index];//用随机位置确定比较的基数 while (l<r) { while (l<=r&&arr[l]<=sPoint) { //等值处理,及:如果所有的数小于或等于基数,那么将基数移至最后,防止出现无法划分数组的情况 if(l==right){ if(arr[index]!=arr[right]){ int temp=arr[index]; arr[index]=arr[right]; arr[right]=temp; } break; } l++;//这里就确定了一个左边位置 } while(arr[r]>sPoint&&l<r){ r--; } if (l<r) { int temp=arr[r]; arr[r]=arr[l]; arr[l]=temp; } } if (l-1>=0) { sort2(arr, left,l-1); } sort2(arr, l, right); }
相关文章推荐
- 快速排序的JAVA实现和性能分析
- 快速排序的性能分析
- 快速排序方法Java实现与分析
- 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 快速排序分析与C语言实现
- 经典排序算法设计与分析(插入排序、冒泡排序、选择排序、shell排序、快速排序、堆排序、分配排序、基数排序、桶排序、归并排序)
- scala学习(一)--------------------快速排序代码分析
- 快速排序 优化 详细分析
- 快速排序实现分析
- 快速排序的性能分析
- 元素排序几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 算法分析之——quick-sort快速排序
- 快速排序c++和python对比分析
- 快速排序优化分析
- 浅谈C++之冒泡排序、希尔排序、快速排序、插入排序、堆排序、基数排序性能对比分析(好戏在后面,有图有真相)
- 快速排序的分析及c语言代码
- 快速排序的深入分析
- 几种常用的排序算法的分析及java实现(希尔排序,堆排序,归并排序,快速排序,选择排序,插入排序,冒泡排序)
- 快速排序复杂度的分析