我的排序算法是否正确?为什么合并排序比快速排序需要更少的迭代?

时间:2018-06-07 15:08:30

标签: javascript algorithm sorting

我一直在尝试各种排序算法的迭代次数。我一直试图找出哪些需要执行大多数迭代。我将迭代定义为循环迭代或函数执行(为了考虑递归)。在性能方面,快速排序和合并排序似乎比冒泡排序要快得多。如果数组中的项目较少,则快速排序似乎更快。这可能是因为我的快速排序算法效率不高。

我的问题是快速排序比合并排序更少的迭代,如果是这样的话。我还在下面列出了我的代码,以防我的算法不正确。谢谢。

function quickSort(arr){
        iter++;
        let length = arr.length;
        let pivot_index =  [length-1]; //Math.floor(Math.random() * [length -1]);
    let index = 0;
    while(pivot_index>index){
        iter++;
        if(arr[pivot_index]<arr[index]){
            let temp = arr[index];
            arr[index] = arr[pivot_index-1];
            arr[pivot_index-1] = arr[pivot_index] ;
            arr[pivot_index] = temp;
            --pivot_index
        }
        else
            ++index;
    }

    if(length>3)
        return  quickSort(arr.slice(0, pivot_index)).concat([arr[pivot_index]],quickSort(arr.slice(pivot_index+1)));
    else
        return arr;
}



function selectionSort(arr){
    let numIterations = 0;
    for(let i = 0; i<arr.length-1; i++){
        numIterations+=1;
        for(let j = i +1; j<arr.length; j++){
            if( arr[i] > arr[j]){
                let temp = arr[i];
                arr[i] = arr[j];
                arr[j] = temp;
            }
            numIterations+=1;
        }
    }
    return {"num_iterations": numIterations, "arr":arr}

}


function bubbleSort(arr){

    let numIterations = 0;
    let count = 0;
    do{
        var swapped = false;
        numIterations+=1;
        count+=1;
        for(let i = 0;i<arr.length-count;i++){
            numIterations+=1;
            if(arr[i]>arr[i+1]){
                let temp = arr[i];
                arr[i] = arr[i+1];
                arr[i+1] = temp;
                swapped = true;
            }
        }

    } while(swapped == true)
    return {"num_iterations": numIterations, "arr":arr}
}

function mergeSort(arr){
    iter+=1;

    if(arr.length>1){
        let divsor = arr.length + 1;
        let arr_left_half = arr.slice(0,parseInt(divsor / 2));
        let arr_right_half = arr.slice(parseInt( divsor / 2));
        arr = null;
        var tup_arr = [mergeSort(arr_left_half), mergeSort(arr_right_half)];

    }else
        return arr;

    let l = []

    while(tup_arr[0].length > 0 || tup_arr[1].length > 0){
        iter+=1;
        let arr1_length = tup_arr[0].length;
        let arr2_length = tup_arr[1].length;
        if(arr1_length > 0 && arr2_length > 0){
            if(tup_arr[0][0] > tup_arr[1][0])
                l.push(tup_arr[1].shift());
            else
                l.push(tup_arr[0].shift());
        }
        else if( arr1_length > 0)
            l.push(tup_arr[0].shift());
        else if(arr2_length > 0)
            l.push(tup_arr[1].shift())

    }
    tup_arr = null;
    return l;

}

let iter = 0;
let arr = []
for(let i =0;i<10000;i++){
   let num =  Math.floor(Math.random() * 10000);
   arr.push(num);
}

let bubble_sort = bubbleSort(arr.slice());
let selection_sort = selectionSort(arr.slice());
let merge_sort = mergeSort(arr.slice());
console.log("Merge Sort Iterations:"+iter);
iter = 0;
let quick_sort = quickSort(arr.slice());
console.log("Quick Sort Iterations:"+iter);
console.log("Selection Sort Iterations:"+selection_sort.num_iterations);
console.log("Bubble Sort Iterations:"+bubble_sort.num_iterations);

1 个答案:

答案 0 :(得分:2)

Mergesort总是递归到⌈log2N⌉深度。在每个递归级别,每个元素都会被比较一次。

Quicksort只有在每次都猜到最佳分区值时才能实现,这不太可能。通常,隔板的一侧将大于另一侧。稍微增加递归深度的平衡是,一旦对分区进行排序,就不再比较其元素。因此,一些元素的比较越多,其他元素的比根据“平均情况”的一个似是而非的定义,快速排序预计将比mergesort进行大约40%的比较。

但是quicksort对于大型数据集具有很大的优势。在mergesort中,合并步骤无法有效地完成。该算法取决于能够使用与原始数据集相同大小的临时存储。

因此,如果您有足够的存储空间,那么mergesort可能会更好。至少那是glibc的作者的判断,除非数据集非常大,否则qsort实现会进行合并。