【数据结构第八周】排序(下)【快速排序】

步骤:

1、从数列中挑出一个元素,称为"基准"或者“主元”(pivot)

2、重新排序数列,所有元素比基准值小的摆放在基准前面,所有元素比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分区退出之后,该基准就处于数列的中间位置。这个称为分区(partition)操作

3、递归地把小于基准值元素的子数列和大于基准值元素的子数列排序

 

选主元的时候可以使用“取头、中、尾的中位数”这种方法。

如果你选取第一个元素作为主元,如果一个数列本身就是有序的,用这种办法产生的O(N^2)的复杂度显然是不能接受的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
ElementType Median3( ElementType A[], int Left, int Right )
{
    int Center=(Left+Right)/2;
    if ( A[ Left ] > A[ Center ] )
    {
        Swap( &A[ Left ], &A[ Center ] );
    }
    if (A[ Left ] > A[ Right ])
    {
        Swap( &A[ Left ], &A[ Right ] );
    }
    if (A[ Center ] > A[ Right ] )
    {
        Swap( &A[ Center ], &A[ Right ] );
    }
    /* A[ Left ] <= A[ Center ] <= A[ Right ] */
    Swap( &A[ Center ], &A[ Right-1 ] ); /* 将pivot藏到右边 */
     
    /* 只需要考虑 A[ Left+1 ] ... A[ Right–2 ] */
    return &A[ Right-1 ];
}

对小规模的数据(例如N不到100)可能还不如插入排序快 。

解决方案:

当递归的数据规模充分小,则停止递归,直接调用简单排序(例如插入排序)

在程序中定义一个Cutoff的阈值

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
void Quicksort( ElementType A[], int Left, int Right )
{
    if ( Cutoff <= Right-Left )
    {
        Pivot = Median3( A, Left, Right );
     
        i=Left; j=Right–1;
        for( ; ; )
        {
            while ( A[ ++i ] < Pivot ) { }
            while ( A[ ––j ] > Pivot ) { }
            if ( i < j )
            {
               Swap( &A[i], &A[j] );
            }else
            {
                break;
            }
            Swap( &A[i], &A[ Right-1 ] );
            Quicksort( A, Left, i-1 );
            Quicksort( A, i+1, Right );
        }
    }else
    {
        Insertion_Sort( A+Left, Right-Left+1 );
    }
 
}

 

posted @   Summer先生  阅读(201)  评论(0编辑  收藏  举报
点击右上角即可分享
微信分享提示