Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

3种快速排序 #86

Open
any86 opened this issue Mar 28, 2022 · 0 comments
Open

3种快速排序 #86

any86 opened this issue Mar 28, 2022 · 0 comments

Comments

@any86
Copy link
Owner

any86 commented Mar 28, 2022

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;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant