[算法]快速排序之Partition的写法

CLRS上的实现

//loop invariant 
/*
[0:i]是低区
[i+1:j]是高区, 原本属于低区的就应该放到低区,同时把高区中的第一个换出来
*/
int clrs_partition(int* A, int left, int right){
    int i = left-1;
    int tmp = A[right]; //注意是从后面开始

    for (int j = left; j < right; j++){ //不是 <= 初始值是left,不是i
        if (A[j] < tmp){
            i++;
            //i这时候指向高区的第一个元素, j指向一个原本应该属于低区的元素
            swap(A[i], A[j]);

        }
    }
    //sawp
    i++;
    swap(A[i],A[right]);
    //printArr()
    return i;
}

另一种实现

//loop invariant:
//每次放入hole之前(可以作为一种方法,即不一定非要等循环结束再看invariant)
//[left:i-1] 的元素一定小于tmp
//[j-1:right] 的元素一定大于tmp
//移动i的时候 hole在j处(右边就是高区)
//移动j的时候 hole在i处(左边就是低区)
int my_partition(int* A, int left, int right){
    const int l = left;
    const int r = right;

    int tmp = A[left];
    int hole = left;
    int i = left;
    int j = right;
    bool toggle = false;
    while (i < j){ //注意这里是 <=  !!!
        if (toggle)
        {
            if (A[i]>tmp){
                A[hole] = A[i]; //填上坑
                hole = i; //空出一个位置,放比tmp小的
                toggle = false;
            }
            else{ //注意这个else, 不能去掉,否则, 
                //如果去掉了, loop invariant 就变成了 [left:i-2]是低区, [j+2:right]是高区
                //移动i的时候 hole在j+1处(右边就是高区)
                //移动j的时候 hole在i-1处(左边就是低区)
                //i==j 退出循环的时候, hole , i(j) 或者 i(j),hole,。。。。有点乱。。
                i++;
            }
        }
        else
        {
            if (A[j] < tmp){
                A[hole] = A[j]; //填上坑
                hole = j;//空出一个位置,放比tmp大的
                toggle = true;
            }
            else
            {
                j--;
            }
        }
    }
    A[hole] = tmp;
    return hole;
}

你可能感兴趣的:(算法导论,clrs,算法)