排序

排序

快速排序

快速排序算法说下,基点怎么选?如果一个数组是已经排序好的怎么选基点?**

  • 数组元素随机,取固定基准;
  • 数组元素已排序或逆序,取随机基准;
  • 更好的方法:三数取中,选取数组开头,中间和结尾的元素,通过比较,选择中间的值作为快排的基准。

优化

  • 数组较小时选择插入排序
  • 相同元素聚合

这里效率最好的快排组合 是:三数取中+插排+聚集相等元素,它和STL中的Sort函数效率差不多

聚集相同元素的话就是把相同的元素都聚集到中间,然后将左边和右边分开的时候可以减少一些元素。

//快速排序
function quickSort(arr){
    //debugger;
    let right = arr.length - 1
    quick(arr,0,right)
    console.log(arr)
}


function partition(arr,left,right){
    if (left < right) {  
            midu(arr, left, right);
            let pivot = right - 1;
            //左指针
            let i = left ;
            //右指针
           let j = right -1 ;
            while (j > i) {
                while (j > i && arr[i] < arr[pivot]) {i++}
                while (j > i && arr[j] >= arr[pivot]) {j--}
                if (i < j) {
                    swap(arr, i, j);
                }else{
                    break;
                }
              
            }
            if( i == j ) {swap(arr,i,pivot)}
            return i;
            
        }
}
function quick(arr,left,right){
    if(left < right){
        let i = partition(arr,left,right)
        quick(arr, left, i - 1);
        quick(arr, i + 1, right);
    }
    
        
}

function midu(arr,left,right){ 
    let mid = left+((right-left)>>1);// >> 优先级低于 + -
    //  也可以写成let mid =  Math.floor(left+right/2)
        if (arr[left] > arr[mid]) {
            swap(arr, left, mid);
        }
        if (arr[left] > arr[right]) {
            swap(arr, left, right);
        }
        if (arr[right] < arr[mid]) {
            swap(arr, right, mid);
        }
        swap(arr, right - 1, mid);
}


function  swap(arr,a,b){
    let temp = arr[a];
        arr[a] = arr[b];
        arr[b] = temp;
}

归并排序

//归并排序

function  mergeSort(array){
    debugger;
    return  mergeSortRec(array);
}
     
function  mergeSortRec(array){
    var length = array.length; 
    if(length === 1) {  
    return array; }   
    var mid = Math.floor(length / 2), 
    left = array.slice(0, mid), 
    right = array.slice(mid, length); 
    return merge(mergeSortRec(left), mergeSortRec(right));
}

function  merge(left, right){
    var result = [], 
    il = 0,
    ir = 0; 
    while(il < left.length && ir < right.length) {    
        if(left[il] < right[ir]) {       
            result.push(left[il++]);    
        } else{       
            result.push(right[ir++]); // {10}     
        }   
    } 
    while (il < left.length){     // {11}     
        result.push(left[il++]);   
    } 
    while (ir < right.length){    // {12}     
        result.push(right[ir++]);  
    } 
    return result; // {13} 
    
}

插入排序

//插入排序
function insertSort(arr) {
    debugger;
    for(let i = 1; i < arr.length; i++) {
        let j, temp = arr[i];
        for(j = i; j > 0 && arr[j - 1] > temp; j --) {
            arr[j] = arr[j - 1];
        }
        arr[j] = temp;
    }
}

优化

插入排序前面的元素是有序的,可以采用二分查找的方式

堆排序

function heapSort(array) {
    //debugger;   
    var heapSize = array.length;   
    buildHeap(array); //{1} 
    while (heapSize > 1) {     
        heapSize--;     
        swap(array, 0, heapSize); //{2}     
        heapify(array, heapSize, 0); //{3}   
    } 
    console.log(array)
};


//建堆
function buildHeap(array){   
  var heapSize = array.length;   
  for (var i = Math.floor(array.length / 2); i >= 0; i--) {    
    heapify(array, heapSize, i);   
  } 
};

//父节点和两个子节点的比较过程
function heapify(array, heapSize, i){
    var left = i * 2 + 1,
    right = i * 2 + 2,
    largest = i;
    if (left < heapSize && array[left] > array[largest]) {
        largest = left;
    }
    if (right < heapSize && array[right] > array[largest]) {
        largest = right;
    }
    if (largest !== i) {
        swap(array, i, largest);
        heapify(array, heapSize, largest);
    }
    
};

选择排序

function selectionSort(arr) {
     debugger;
    // 选多少次
    for(let i = 0; i < arr.length - 1; i ++) {
        let minIndex = i;
        // 在arr[i + 1, ] 中找最小值索引, i+1 代表有序的下一个数,我们默认第一个元素是最小的
        for(let j = i + 1; j < arr.length; j ++) {
            if(arr[j] < arr[minIndex]) {
                minIndex = j;
            }
        }
        if(minIndex != i) {
            // 交换
            let temp = arr[minIndex]
            arr[minIndex] = arr[i]
            arr[i] = temp;
        }
    }
}


优化

原来的选择排序是每次选择一个最小的值放在最前面

改进措施:每次循环找到最大值和最小值,然后最小值和第一个交换,最大值和最后一个交换

冒泡排序

优化

算法的稳定性:冒泡,快排,归并,基数是稳定的

posted @ 2020-03-30 23:53  windalm  阅读(127)  评论(0编辑  收藏  举报