javascript排序算法

130 阅读2分钟

冒泡排序

冒泡排序,有时被称为下沉排序,是一种简单的排序算法,它反复遍历要排序的列表,比较每一对相邻项,如果它们的顺序错误(升序或降序排列),则交换它们。重复传递列表,直到不需要交换,这表示列表已排序。

function BubbleSort (arr) {
    if (arr.length <= 1) return []
    for (let i = 0; i <arr.length;i++) {
        for(let j = 0; j < arr.length - 1; j++) {
            if (arr[j] > arr[j + 1]) {
                [arr[j], arr[j+1]] = [arr[j+1], arr[j]]
            }
        }
    }
    return arr
}

插入排序

插入排序是一种简单的排序算法,它一次构建一个项目的最终排序数组(或列表)。与更高级的算法(如快速排序、堆排序或合并排序)相比,它在大型列表上的效率要低得多。

  1. 从第一个元素开始,该元素可以认为已经被排序;

  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描;

  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置;

  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置;

  5. 将新元素插入到该位置后;

  6.  重复步骤2~5。

    function insertSort (arr) { if (arr.length <= 1) return [] for (let i = 1; i < arr.length; i++) { let temp = arr[i] let j = i - 1 while (j >= 0 && temp < arr[j]) { arr[j + 1] = arr[j] j-- } arr[j+1] = temp } return arr } insertSort([4,6,1,2,3])

选择排序

选择排序是一种排序算法,特别是就地比较排序。它的时间复杂度为O(n2),使得它在大型列表上效率低下,并且通常比类似的插入排序的性能更差。选择排序以其简单性著称,在某些情况下,特别是在辅助内存有限的情况下,它比更复杂的算法具有性能优势。

  1. 从未排序的序列中找到最大的元素,放在已排序的序列的末尾,重复该步骤直到所有元素排序完毕

    function selectionSort (arr) { if (arr.length <= 1) return [] for (let i = 0; i < arr.length - 1; i++) { let mIndex = i for (let j = i + 1; j < arr.length; j++) { if (arr[j] < arr[mIndex]) { mIndex = j } } if (mIndex !== i) { [arr[i], arr[mIndex]] = [arr[mIndex], arr[i]] } } return arr } selectionSort([4,6,1,2,3])

堆排序

let len = 0
function heapify (arr, i) {
    let c1 = 2 * i + 1
    let c2 = 2 * i + 2
    let max = i
    if (c1 < len && arr[c1] > arr[max]) {
        max = c1
    }
    if (c2 < len && arr[c2] > arr[max]) {
        max = c2
    }
    if (max != i) {
        [arr[max], arr[i]] = [arr[i], arr[max]]
        heapify(arr, max)
    }
}
function heapSort (arr) {
    // 创建大顶堆
    len = arr.length
    for (let i = Math.floor(len / 2); i >= 0; i--) {
        heapify(arr, i)
    }
    for (let i = len - 1; i > 0; i--) {
        [arr[0], arr[i]] = [arr[i], arr[0]]
        len--
        heapify(arr, 0)
    }
    console.log(arr)
    return arr
}
heapSort([4,1,10,5,3,7,13,2])

快速排序

function quickSort (arr) {
    if (arr.length <= 1) return arr
	const compareArr = arr.splice(0, 1)[0]
    let left = []
    let right = []
    for (let i = 0; i < arr.length; i++) {
        if (arr[i] <= compareArr) {
            left.push(arr[i])
        } else if (arr[i] >= compareArr) {
            right.push(arr[i])
        }
    }
    return quickSort(left).concat([compareArr], quickSort(right))
}
quickSort([4,1,10,5,3,7,13,2])

归并排序

function mergeSort (arr) {
    if (arr.length < 2) return arr
    const len = arr.length
    let middle = len >> 1,
        left = arr.slice(0, middle),
        right = arr.slice(middle)
    return merge(mergeSort(left), mergeSort(right))
}
function merge (left, right) {
    const result = []
    while (left.length && right.length) {
        if (left[0] <= right[0]) {
            result.push(left.shift())
        } else {
            result.push(right.shift())
        }
    }
    while (left.length) {
        result.push(left.shift())
    }
    while (right.length) {
        result.push(right.shift())
    }
    return result
}
mergeSort([4,1,10,5,3,7,13,2])

希尔排序

function shellSort (arr) {
    const len = arr.length
    if (len < 2) return arr
	let gap = len >> 1
    while (gap > 0) {
        for (let i = 0; i < len - gap; i++) {
            let currentIndex = i
            let gapShiftedIndex = gap + i
            while (currentIndex >= 0) {
                if (arr[gapShiftedIndex] < arr[currentIndex]) {
                    [arr[gapShiftedIndex], arr[currentIndex]] = [arr[currentIndex], arr[gapShiftedIndex]]
                }
                gapShiftedIndex = currentIndex
                currentIndex = currentIndex - gap
            }
        }
        gap = gap >> 1
    }
    return arr
}
shellSort([4,1,10,5,3,7,13,2])

计数排序

function countingSort (originalArray, min = undefined, max = undefined) {
	let detectedMax = max || 0
	let detectedMin = min || 0
	if (!detectedMax || !detectedMin) {
		originalArray.forEach(element => {
			if (element < detectedMin) {
				detectedMin = element
			}
			if (element > detectedMax) {
				detectedMax = element
			}
		})
	}
	const buckets = Array.from({length: (detectedMax - detectedMin + 1)}).fill(0) // 创建累计数组,并填充0
    let sortedArray = [] //创建回写数组
    originalArray.forEach(element => buckets[element - detectedMin] += 1) // 累计数组频次计算
    
    for (let bucketIndex = 1; bucketIndex < buckets.length; bucketIndex += 1) {
      buckets[bucketIndex] += buckets[bucketIndex - 1];
    }
    
    buckets.pop();
    buckets.unshift(0);
    
    for (let i = 0; i < originalArray.length; i++) {
    	const element = originalArray[i]
    	const elementSortedPosition = buckets[element - detectedMin]
    	sortedArray[elementSortedPosition] = element
    	buckets[element - detectedMin] += 1
    }
    return sortedArray
}
countingSort([4,1,10,5,3,7,13,2])

基数排序

function RadixSOrt (originalArray) {
    let sortedArray = [...originalArray]
    const numLenth = Math.floor(Math.log10(Math.max(...originalArray))) + 1
    for (let i = 0; i < numLenth; i ++) {
        let buckets = Array.from({length: 10}, () => [])
        const modded = 10 ** (i+1)
        const divided = 10 ** i
        sortedArray.forEach(element => {
            if (element < divided) {
                buckets[0].push(element)
            } else {
                const currentDigit = Math.floor((element % modded) / divided)
                buckets[currentDigit].push(element)
            }
        })
        sortedArray = buckets.reduce((acc, val) => {
            console.log(acc)
            return [...acc, ...val]
        }, [])
    }
    return sortedArray
}
RadixSOrt([4,1,10,5,3,7,13,2])