排序算法

119 阅读3分钟

排序算法

let arr = [2,1,3,5,6,4,9,8,7];

/*冒泡排序*/
function min(arr) {
    for (let i = 0; i < arr.length-1; i++){
        for (let j = 0; j < arr.length-i-1; j++){
            if (arr[j] > arr[j+1]){
                let temp = arr[j];
                arr[j] = arr[j+1];
                arr[j+1] = temp;
            }
        }
    }
    return arr;
}
//console.log(min(arr));


/*
* 选择排序
* 把每一项与后面各项进行对比,然后把最小的元素放到最前面,第二次比较的时候,放到最前面的元素排除在比较范围之外,
* 最小的元素的索引一定是当前元素的索引
* 为什么i<arr.length-1, 假如四项比,第一个元素需要和后面元素比三次,所以小于长度-1就行
*
* ps 第二层循环的时候,j<arr.length 这句代码不需要加入 -i-1,因为let j = i+1已经控制了比较的次数,
* 如果加上的话,后面有些元素会比较不到
*
* */
function selectSort(arr) {
    for (let i = 0; i<arr.length-1;i++){
        let minIndex = i;   // 此轮比较中最小元素索引

        // 获取此轮比较中最小元素索引
        for (let j = i+1; j<arr.length; j++){
            if (arr[i] > arr[j]){
                minIndex = j;
            }
        }
        // 因为最小元素必须置于首位,这里判断是否进行元素交换
        if (i !== minIndex){
            let temp = arr[i];
            arr[i] = arr[minIndex];
            arr[minIndex] = temp;
        }
    }
    return arr;
}
console.log(selectSort(arr));
/*
* 快速排序
* 在数据集之中,选择一个元素作为"基准"(pivot),
* 所有小于"基准"的元素,都移到"基准"的左边;所有大于"基准"的元素,都移到"基准"的右边
* 对"基准"左边和右边的两个子集,不断重复第一步和第二步,直到所有子集只剩下一个元素为止
* */
function quickSort(arr) {
    if (arr.length <= 1){
        return arr;
    }

    // length别忘记除以2
    let pivotIndex = Math.floor(arr.length/2);
    let pivot = arr.splice(pivotIndex, 1)[0];

    let left = [];
    let right = [];

    for (let i=0; i<arr.length; i++){
        if (arr[i] < pivot){
            left.push(arr[i]);
        } else {
            right.push(arr[i]);
        }
    }
    // 注意concat合并的是数组,所以pivot要加上中括号
    return quickSort(left).concat([pivot], quickSort(right))
}
console.log(quickSort(arr));

/*
* 合并排序法是将两个(或两个以上)有序表合并成一个新的有序表,即把待排序序列分为若干个子序列,
* 每个子序列是有序的。然后再把有序子序列合并为整体有序序列。 将已有序的子序列合并,得到完全有序的序列;
* 即先使每个子序列有序,再使子序列段间有序
* */
function mergeSort(arr) {
    if (arr.length === 1){
        return arr;
    }

    let middle = Math.floor(arr.length/2);
    let left = arr.slice(0,middle);
    let right = arr.slice(middle);

    return merge(mergeSort(left), mergeSort(right));
}

function merge(left, right){
    let result = [];
    while (left.length>0 && right.length>0){  // 进入循环的是两个只有一个元素的数组,判断出最小放入result,另一个比较大的就用concat
        if (left[0] < right[0]){
            result.push(left.shift()); //把最小的最先取出,放到结果集中
        } else {
            result.push(right.shift())
        }
    }
    return result.concat(left).concat(right); //剩下的就是合并,这样就排好序了
}

console.log(mergeSort(arr));

/*
* 计数排序
* 把数组的每一项当作key,出现次数当作value做成一个哈希表(对象),遍历此数组,拿出最大值。
* 第二次就遍历哈希表,从0到最大值,如果i在哈希表中存在(指key),则进行push,出现多次,则对哈希值做出判断,在push
* */
function hashSort(arr) {

    let hashTable = {}, max = 0, result = [];
    for (let i = 0; i < arr.length; i++){
        if (!(arr[i] in hashTable)){
            hashTable[arr[i]] = 1;
        } else {
            hashTable[arr[i]] += 1;
        }
        if (arr[i] > max){
            max = arr[i];
        }
    }

    for (let j = 0; j <= max; j++){
        if (j in hashTable){
            for (let k = 0; k < hashTable[j]; k++){
                result.push(j);
            }
        }
    }
    return result;
}
console.log(hashSort(arr));