算法导论之七快速排序

1.        快速排序也采用了分治思想,下面是对子数组A[p..r]进行快速排序的三步分治过程:

分解:数组A[p..r]被划分为两个子数组(可能为空)A[p..q-1]和A[q+1..r],使得A[p..q-1]中的每

一个元素都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每一个元素。其中,计算

下标q也是划分过程的一部分。

解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序。

合并:因为子数组都是通过原址排序的,因此不需要合并操作

 

伪代码实现快速排序:

QUICK-SORT(A,p,r)

         ifp < r

                   q= PARTITION(A,p,r)

                   QUICK-SORT(A,p,q-1)

                   QUICK-SORT(A,q+1,r)

PARTITION过程实现了对子数组A[p..r]的原址重排:

 PARTITION(A,p,r)

         x= A[r]

         i= p – 1

         forj = p to r – 1

                   ifA[j] <= x

                            i= i + 1

                            exchangeA[i] and A[j]

         exchangeA[i + 1] and A[r]

         returni + 1

分析:该过程选择A[r]作为主元,并围绕它来划分子数组A[p..r]。for循环中的每一区域均满足循环不变量,即对于任意的下标k,存在:

(1) 若p <= k <= i,则A[k] <=A[r]

(2) 若i + 1 <= k <= j – 1,则A[k] > A[r]

(3) 若k = r,则A[k] = x

在最后两行中,通过将主元与最左的大于x的元素进行交换,就可以将主元移到它在数组中的正确位置上,并返回主元的新下标。

2.        快速排序的性能

快速排序的运行时间依赖于划分是否平衡,如果是平衡的,则快速算法性能与归并排序一样,如果不平衡,则性能接近于插入排序。

3.        快速排序的程序代码:

#include<stdio.h>

 

//对R[i..j]做划分,并返回基准记录的位置

intPartition(int *R,int i,int j)

{

         int pivot=R[i];   //用区间的第一个记录作为基准

         while (i<j)          //从区间两端交替向中间扫描,直至i=j为止

         {

                   while (i<j &&R[j]>=pivot)         //pivot相当于在位置i上

                   {

                            j--;    //从右至左扫描,查找第一个关键字小于pivot的记录R[j]

                   }

                   if (i<j)

                   {

                            R[i++]=R[j];

                   }

                   while (i<j &&R[i]<=pivot)

                   {

                            i++;

                   }

                   if (i<j)

                   {

                            R[j--]=R[i];

                   }

         }

         R[i]=pivot;

         return i;

}

 

voidQuickSort(int *R,int low ,int high)

{

         int pivotpos;

         if (low<high)

         {

                   pivotpos=Partition(R,low,high);

                   QuickSort(R,low,pivotpos-1);

                   QuickSort(R,pivotpos+1,high);

         }

}

 

intmain()

{

         int S[10]={23,12,4,8,11,3,34,15,2,1};

         QuickSort(S,0,9);

 

         for (int i=0;i<10;i++)

         {

                   printf("%d  ",S[i]);

         }

         printf("\n");

}

4.        快速排序的随机化版本

/************************************************************************/

/*    

         快速排序算法:

         分解:数组A[p..r]被划分为两个子数组A[p..q-1]和A[q+1..r],使得A[p..q-1]

                     中的每一个元素都小于等于A[q],而A[q]也小于等于A[q+1..r]中的每个数。

                     其中,计算下边q也是划分过程的一部分

         解决:通过递归调用快速排序,对子数组A[p..q-1]和A[q+1..r]进行排序

         合并:因为子数组都是原址排序的,所以不需要合并操作,数组A[p..r]已经有序

 

         QUICKSORT(A,p,r)

         if p<r

                   q=PARTITION(A,p,r)

                   QUICKSORT(A,p,q-1)

                   QUICKSORT(A,q+1,r)

 

         PARTITION过程实现了对子数组A[p..r]的原址重排

 

         PARTITION(A,p,r)

         x=A[r]

         i=p-1

         for j=p to r-1

                   if A[j]<=x

                            i=i+1

                            exchange A[i] withA[j]

         exchange A[i+1] with A[r]

         return i+1

 

         快速排序:最坏运行时间是O(n^2),期望的运行时间为θ(nlgn)

*/

/************************************************************************/

#include<stdio.h>

#include<math.h>

#include<stdlib.h>

#include<time.h>

 

intnum=10;

 

voidswap(int *a,int *b)

{

         int temp;

         temp=*a;

         *a=*b;

         *b=temp;

}

 

voidPrintArray(int arr[])

{

         for (int i=0;i<10;i++)

         {

                   printf("%d",arr[i]);

         }

}

 

intPartition(int *arr,int beg,int end)

{

         int j;

         int sentline1=arr[end];

         int i=beg-1;

 

         for (j=beg;j<=end-1;j++)

         {

                   if (arr[j]<=sentline1)

                   {

                            i++;

                            swap(&arr[i],&arr[j]);

                   }

         }

 

         swap(&arr[i+1],&arr[end]);

         printf("\n排序过程:\n");

         PrintArray(arr);

         return i+1;

}

 

intRadomPartition(int *arr,int beg,int end)

{

         int i=beg+rand()%(end-beg+1);

         swap(&arr[i],&arr[end]);

         return Partition(arr,beg,end);

}

 

voidRandomQuickSort(int *arr,int beg,int end)

{

         if (beg<end)

         {

                   intpivot=RadomPartition(arr,beg,end);

                   printf("\n随机选择 arr[%d](%d)",pivot,arr[pivot]);

                   RandomQuickSort(arr,beg,pivot-1);

                   printf("\n随机选择 arr[%d](%d)",pivot,arr[pivot]);

                   RandomQuickSort(arr,pivot+1,end);

         }

}

intmain()

{

         int i;

         int arr[10];

 

         srand(time(0));

         for (i=0;i<10;i++)

         {

                   arr[i]=rand()%100+1;

         }

 

         printf("初始数组:");

         PrintArray(arr);

 

         RandomQuickSort(arr,0,9);

 

         printf("\n最后结果:");

         PrintArray(arr);

 

         return 0;

}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

mengrennwpu

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值