快速排序--阮一峰老师的方法究竟存在什么争议?

2020-02-25  本文已影响0人  宋乐怡

R:

var quickSort = function(arr) {
 
  if (arr.length <= 1) { return arr; }
 
  var pivotIndex = Math.floor(arr.length / 2);
 
  var pivot = arr.splice(pivotIndex, 1)[0];
 
  var left = [];
 
  var right = [];
 
  for (var i = 0; i < arr.length; i++){
 
    if (arr[i] < pivot) {
 
      left.push(arr[i]);
 
    } else {
 
      right.push(arr[i]);
 
    }
 
  }
 
  return quickSort(left).concat([pivot], quickSort(right));
 
};

思路:
1.选择中间元素作为基数。
2.新开辟两块内存空间,分别存放比基数小的值和比基数大的值。
3.递归左右数组,拼接中间值

争议:
1.取中间值的方式不直观,下标法是数组效率最高的方式, 调用splice函数是额外的开销。
2.新开辟的两个数组是不必要的内存开销。

优化:
从存疑的两个方向来优化代码
1.key的位置究竟是哪,其实并不重要,所以就取第一个就ok。
2.原地交换,不开辟新空间。

var arr=[5,7,2,9,3,8,4,7,1];
// 每次选择最左边的数作为基数
function quickSort(arr){
  if (arr.length<2) { return arr; }
  // 定义左指针
  var left=0;
  // 定义右指针
  var right=arr.length-1;
  //开启每一轮的排序
  while(left<right){
    // 寻找右边比arr[0]小的数的下标
    while(arr[right]>=arr[0] && left<right){
      right=right-1;
    }
    // 寻找左边比arr[0]大的数的下标
    while(arr[left]<=arr[0] && left<right){
      left++;
    }
    //当左边指针与右边指针相遇后,交换arr[0]与当前两个指针所在的元素
    if (right==left) {
      let mid=arr[right];
      arr[right]=arr[0];
      arr[0]=mid;
      break;
    }
    // 当左指针小于右指针的位置,交换两个指针当前位置的元素
    let tem=arr[right];
    arr[right]=arr[left];
    arr[left]=tem;
  }
  //递归实现
  return quickSort(arr.slice(0,left)).concat(arr.slice(left,right+1)).concat(quickSort(arr.slice(right+1)));
}
//对数组进行排序
console.log(quickSort(arr));
上一篇下一篇

猜你喜欢

热点阅读