any86/Notes

3种快速排序

Opened this issue · 0 comments

any86 commented
type Compare<T> = (pivotItem: T, currentItem: T) => number;
/**
 * 比较函数
 * @param pivotItem 待比较值 
 * @param currentItem 当前值
 * @returns 数组,大于0正序,反之倒序
 */
function compareNumber(pivotItem: number, currentItem: number): number {
    return pivotItem - currentItem;
}

export function quickSort3<Item = number>(list: Item[], compareFn: Compare<Item> = compareNumber as any): Item[] {
    const { length } = list;
    if (1 > length) return list;
    const pivotItem = list[0];
    const left: Item[] = [];
    const right: Item[] = [];
    for (let i = 1; i < length; i++) {
        const currentItem = list[i];
        if (0 > compareFn(pivotItem, currentItem)) {
            left.push(currentItem);
        } else {
            right.push(currentItem);
        }
    }
    return [...quickSort(left, compareFn), pivotItem, ...quickSort(right, compareFn)];
}


/**
 * 快速排序(原地排序)
 * 通过参数可以选择被排序的索引范围
 * @param array 数组
 * @param startIndex 起始索引
 * @param endIndex 结束索引
 * @returns 
 */
export function quickSort2<Item = number>(array: Item[], startIndex = 0, endIndex = array.length - 1,compareFn: Compare<Item>) {
    if (startIndex >= endIndex) {
        return array
    }
    const pivotIndex = partition(array, startIndex, endIndex,compareFn);
    quickSort2(array, startIndex, pivotIndex - 1,compareFn)
    quickSort2(array, pivotIndex + 1, endIndex,compareFn)
    return array;
}

/**
 * 分区, 
 * @param array 
 * @param startIndex 
 * @param endIndex 
 * @returns 
 */
function partition<Item = number>(array: Item[], startIndex: number, endIndex: number, compareFn: Compare<Item>) {
    // 参考值
    const pivot = array[startIndex];
    // 分割标准值的索引
    let divideIndex = startIndex;
    for (let i = startIndex + 1; i <= endIndex; i++) {
        if (0 > compareFn(array[i], pivot)) {
            divideIndex++;
            swap(array, divideIndex, i);
        }
    }
    swap(array, divideIndex, startIndex);
    return divideIndex;
}


function swap(array: unknown[], i: number, j: number) {
    const v = array[i];
    array[i] = array[j];
    array[j] = v;
}

/**
 * 快速排序(原地排序)
 * 通过参数可以选择被排序的索引范围
 * 参考: https://zhuanlan.zhihu.com/p/109971850
 * @param array 数组
 * @param startIndex 起始索引
 * @param endIndex 结束索引
 * @returns 
 */
export function quickSort<Item = number>(array: Item[], compareFn: Compare<Item> = compareNumber as any): Item[] {
    const startIndex = 0;
    const endIndex = array.length - 1;

    const stack: [number, number][] = [];
    stack.push([startIndex, endIndex]);
    while (0 !== stack.length) {
        const [startIndex, endIndex] = stack.pop()!;
        const pivotIndex = partition(array, startIndex, endIndex, compareFn);
        if (startIndex < pivotIndex - 1) {
            stack.push([startIndex, pivotIndex - 1]);
        }
        if (pivotIndex + 1 < endIndex) {
            stack.push([pivotIndex + 1, endIndex]);
        }
    }
    return array;
}