(C语言浙大版)实现快速排序并解析主元选择(附测试用例)


本博文源于浙江大学《数据结构》,快速排序的设计体现了分而治之的思想,如何分而治之在程序中用处比较大。如果粗暴选择,那就会造成O(N^2)的时间复杂度,经过多年来学者的探究,选主元无非这几种情况:

选主元

第一种 随机取

利用rand()函数取,rand函数是c语言产生随机数的一个函数,如果大家对随机数不是非常了解,需要看这篇博主写的文章,较清晰的阐述rand函数使用
(c语言)qsort及rand使用指南(附测试用例)
这里的随机取,无非是用rand取下标,这种因为调用浪费时间,所以很快被淘汰

第二种 三者的中位数

这种取法就是比较,将中位数甩出去,保证分而治之两个都是有序列,不然就出现这种情况,
在这里插入图片描述

快速排序算法特点

  • 快速排序的趟数取决于递归树的深度。
  • 在这里插入代码片
时间复杂度:nlogn
空间复杂度:log2n 最坏 O(n)
总的关键字比较次数KCN O(n^2/2)
算法特点:

 - 记录非顺次的移动导致排序是不稳定的。
 - 排序过程中需定位的下界和上界,所以适合用于顺序结构,很难用于链式结构。
 - 当n较大,平均情况下快速排序是所有内部排序方法中速度最快的一种,所以其适合初始记录无序,n较大时的情况。

快速排序的缺失

因为采用递归,小规模数据不适宜采用快速排序,利用选择排序就差不多行了,随着要排序的数量不断增大,大规模数据考虑用快速排序

测试用例

	int a[MAXN];
	srand(time(NULL));
    for (int i = 0; i < MAXN; i++)
		a[i] = rand()%(1000)+1; 

博主是用随机数产生[1,1000]范围之间的随机数,最后将其排序,效果比较显著

效果图

在这里插入图片描述

源码(严蔚敏版本)

int Partition(int r[],int low,int high){
    r[0] = r[low];
    int pivotkey = r[low];
    while(low < high){
        while(low < high && r[high]>=pivotkey) --high;
        r[low] = r[high];
        while(low<high && r[low]<=pivotkey) ++low;
        r[high] = r[low];
    }
    r[low] = r[0];
    return low;
}
void Qsort(int r[],int low,int high){
    if(low<high){
        int pivotloc = Partition(r,low,high);
        Qsort(r,low,pivotloc-1);
        Qsort(r,pivotloc+1,high);
    }
}
void QuickSort(int r[]){
    Qsort(r,1,4);
}

源码附上(浙大版)

//qsort-1-2.c
#include<stdlib.h>
#include<stdio.h>
#include<time.h>
#define MAXN 100
typedef int ElementType;
void Swap(int *X,int *Y)
{
	int tmp = *X;
	*X = *Y;
	*Y = tmp;
}

void InsertionSort(ElementType A[], int N)
{
	int i = 0;
	for(int P=1;P<N;P++) {
		int Tmp = A[P];
		for(i = P;i>0 && A[i-1] > Tmp;i--)
			A[i] = A[i-1];
		A[i] = Tmp;
	}
}

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];  /* 返回基准Pivot */
}
 
void Qsort( ElementType A[], int Left, int Right )
{ /* 核心递归函数 */ 
     int Pivot, Cutoff, Low, High;
       
     if ( Cutoff <= Right-Left ) { /* 如果序列元素充分多,进入快排 */
          Pivot = Median3( A, Left, Right ); /* 选基准 */ 
          Low = Left; High = Right-1;
          while (1) { /*将序列中比基准小的移到基准左边,大的移到右边*/
               while ( A[++Low] < Pivot ) ;
               while ( A[--High] > Pivot ) ;
               if ( Low < High ) Swap( &A[Low], &A[High] );
               else break;
          }
          Swap( &A[Low], &A[Right-1] );   /* 将基准换到正确的位置 */ 
          Qsort( A, Left, Low-1 );    /* 递归解决左边 */ 
          Qsort( A, Low+1, Right );   /* 递归解决右边 */  
     }
    else InsertionSort( A+Left, Right-Left+1 ); /* 元素太少,用简单排序 */ 
}

 
void QuickSort( ElementType A[], int N )
{ /* 统一接口 */
     Qsort( A, 0, N-1 );
}
void Print_Array(ElementType A[],int N)
{
	

	for(int i=0;i<N;i++){
		printf("%d ",A[i]);
		if((i+1)%5==0) printf("\n");
	}
}		
int main()
{
	int a[MAXN];
	srand(time(NULL));
    for (int i = 0; i < MAXN; i++)
		a[i] = rand()%(1000)+1; 
	QuickSort(a,MAXN);
	Print_Array(a,MAXN);

	return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值