快速排序

(1)先从数列中取出一个数作为基准数

(2)分区过程:

    将比基准数大于的数全放到它的右边,

    小于或等于它的数全放到它的左边

(3)对区间再进行排序


void quickSort( int A[], int p, int r)
{
    if (p < r)
    {
        int q = Partition( A, p, r);    //步骤(2),其实这样也就确定了基准数的位置,
        quickSort(A, p, q-1);        //所以对步骤(3)的两个区间,就不应该包括基准数
        quickSort(A, q+1, r);
    }
}



实现步骤(2)的方法有多种,现在介绍两种:

第一种:从左到右进行查找,用 border 来指定界限( 它的左边都小于或者等于 基准数, 右边大于基准数),

初始值为 p -1

然后用 j 从左到右循环,  当A[j] 小于或者等于基准数,    { border++;    交换 A[border] 和 A[ j ]   }

void Partirion( int A[], int p, int r)
{
    int x = A[r];
    int border = p-1;
    
    for (int j = p; j < r; j++)
        {
            if( A[j] <= x )
                {
                    border++;
                    exchange( A[border] , A[j]);
                }
        }
    exchange( A[border+1], A[r]);

    return border+1 ;
    
}

例子:

border指向p-1

3
8
9
4
6
7
5

p指向3,                                                                                                    r指向5


j指向3 ,       3 < 5 ,所以

border指向3

3
8
9
4
6
7
5



j指向8 ,        8 > 5 , 所以

border不会自加,仍然指向3        

3
8
9
4
6
7
5


j指向9,        9> 5 ,所以

border不会自加,仍然指向3

3
8
9
4
6
7
5


j指向4,         4 <5 , 所以

border自加,指向8

3 8
9
4
6
7
5

并且交换4和8的位置

3 4
9
8
6
7
5


j指向6,        6 > 5, 所以

border不会自加,仍然指向4

3
4
9
8
6
7
5


指向7,        7> 5, 所以

border不会自加,仍然指向4

3
4
9
8
6
7
5


然后 j 退出循环, 交换 9  和 5 的位置, 即 border+1 和 r 的位置

3
4
5
8
6
7
9


这样基准数5的位置就确定了,然后返回基准数的位置(border + 1)


牢记: border是作为界限,它所指的位置和其所指位置的左边,都小于或者等于基准数


第二种方法:从两边一起向中间查找, 左边找到大于基准数的位置, 右边找到小于或者等于基准数的位置,

然后交换两者的位置。


fore 从左到右查找,back从右到左查找

void Partition( int A[], int p ,int r)
{
    int x = A[r];
    int fore = p;
    int back = r - 1;

    while( fore < back)
    {
        while(  A[fore] <= x && fore < back)
            fore++;
        while( A[back] > x && fore < back)
            back--;
        
        exchange( A[fore], A[back]);
    }                                    //退出时一定时fore == back
                                         //因为fore和back一个一个的加的
                                         //而且可以肯定fore-1(包括自身) 都小于等于x,
                                         // back+1(包括自身) 都大于x
                                        //只有fore和back指向的元素不知道与x的大小
    if( A[fore] > x)
        {
            exchange( A[fore], A[r]);
            return fore;
        }
    else
        {
            exchange(A[fore+1],A[r]);
            return fore+1;
        } 
}











你可能感兴趣的:(快速排序)