19、内部排序之快速排序

    内部排序指排序记录存放在计算机随机存储器中进行的排序过程,外部排序指,由于待排序的记录数量太大,以致排序过程中尚需对外存进行访问的排序过程。

一、快速排序的基本思想

1、快速排序(Quick Sorting)又称分区交换排序,是对冒泡排序算法的改进,是一种基于分组进行互换的排序方法。

2、快速排序的基本思想是:从待排记录序列中任取一个记录Ri作为基准(通常取序列中的第一个记录),将所有记录分成两个序列分组,使排在Ri之前的序列分组的记录关键字都小于等于基准记录的关键字值Ri.key,排在Ri之后的序列分组的记录关键字都大于Ri.key,形成以Ri为分界的两个分组,此时基准记录Ri的位置就是它的最终排序位置。此趟排序称为第一趟快速排序。然后分别对两个序列分组重复上述过程,直到所有记录排在相应的位置上。

在快速排序中,选取基准常用的方法有:

(1)选取序列中第一个记录的关键字值作为基准关键字。这种选择方法简单。但是当序列中的记录已基本有序时,这种选择往往使两个序列分组的长度不均匀,不能改进排序的时间性能。

(2)选取序列中间位置记录的关键字值作为基准关键字。

(3)比较序列中始端、终端及中间位置上记录的关键字值,并取这三个值中居中的一个作为基准关键字。

通常取序列中的第一个记录作为关键字。

3、具体的算法描述如下:

算法中记录的比较和交换是从待排记录序列的两端向中间进行的。设置两个变量i和j,其初值分别是n个待排序记录中第一个记录的位置号和最后一个记录的位置号。在扫描过程中,变量i,j的值始终表示当前所扫描分组序列的第一个和最后一个记录的位置号。将第一个记录R0作为基准记录放到一个临时变量temp中,将R0的位置空出。每趟快速排序,如下进行:

(1)从序列最后位置的记录Rj开始依次往前扫描,若存在temp≤Rj.key ,则令j前移一个位置,即j= j-1,如此直到temp>Rj.key或i=j为止。若i<j,则将记录Rj放入Ri 空出的位置(由变量i指示的位置)。此时Rj位置空出(由变量j指示的位置)。

(2)从序列最前位置的记录Ri开始依次往后扫描,若存在temp≥R[i].key,则令i后移一个位置,即i= i+1,如此比较直到temp<Ri.key或i=j为止。若i<j,则将记录Ri放入Rj 空出的位置(由变量j指示的位置)。此时Ri位置空出(用变量i指示的位置)。使j=j-1,继续进行步骤(1)的操作,即再从变量j所指示的当前位置依次向前比较交换。

在一趟快速排序中,整个过程交替地从后往前扫描关键字值小的记录和从前往后扫描关键字值大的记录并放置到对应端空出的位置中,又空出新的位置。当从两个方向的扫描重合时,即i=j,就找到了基准记录的存放位置。

按照快速排序的基本思想,在一趟快速排序之后,需要重复(1),(2),直到找到所有记录的相应位置。显然,快速排序是一个递归的过程。

如下图中所示,a图为一次快速排序过程,b图为排序全过程。

二、快速排序的C语言描述

三、快速排序的C语言实现

#include"stdio.h"

#include"stdlib.h"

#defineOK 1

#defineMAXSIZE 20

typedefint KeyType;

typedefint Status;

typedefstruct

{

KeyTypekey;

//InfoTypeotherinfo;

}RedType;

typedefstruct

{

RedTyper[MAXSIZE+1];

intlength;

}Sqlist;

StatusPartition(Sqlist &L,int low,int high)

{

//按从小到大的顺序排列

L.r[0]=L.r[low];

int pivotkey;

pivotkey=L.r[low].key;

while(low<high)

       {

       while(low<high&&L.r[high].key>=pivotkey)--high;

       L.r[low]=L.r[high];

       while(low<high&&L.r[low].key<=pivotkey)++low;

       L.r[high]=L.r[low];

    }//while

    L.r[low]=L.r[0];

       return low;

}//Partition

void QSort(Sqlist&L,int low,int high)

{

//对顺序表中的子序列L.r[low..high]作快速排序

       if(low<high)

       {

       int pivotloc;

       pivotloc=Partition(L,low,high);

       QSort(L,low,pivotloc-1);

       QSort(L,pivotloc+1,high);

       }//if

}//QSort

voidQuickSort(Sqlist &L)

{

QSort(L,1,L.length);

}

voidInputL(Sqlist &L)

{

printf("inputthe length:\n");

scanf("%d",&L.length);

printf("inputthe data needed to sort:\n");

for(inti=1;i<=L.length;i++)

       scanf("%d",&L.r[i].key);

}//InputL

intmain()

{

SqlistL;

InputL(L);

QuickSort(L);

printf("thedata after sorting is:\n");

for(inti=1;i<=L.length;i++)

       printf("%d ",L.r[i].key);

returnOK;

}

三、快速排序复杂度分析

其中,Tpass(n)为对n个记录进行一趟快速排序Partition(L,1,n)所用的时间,从算法

                                                                                                                              上式标为(10-8)

            通常,快速排序被认为是在所有同数量级(O(n*logn))中平均性能最

 只要将该记录和L.r[s]互换即可。采用三者中的中值,可

 此时,可改写如上算法,在一趟排序之后比较分割所得两部分的长度,且先对长度短的子序列中的记录进行快速排序,则栈最大深度为O(log(n))。快速排序算法是不稳定排序,对于有相同关键字的记录,排序后有可能颠倒位置。 

发布了278 篇原创文章 · 获赞 31 · 访问量 1万+

猜你喜欢

转载自blog.csdn.net/hopegrace/article/details/104534008
今日推荐