快速排序

一、伪代码(快速排序)

QUICKSORT(A, p, r)

1 if p < r

2    then q ← PARTITION(A, p, r)   

3         QUICKSORT(A, p, q - 1)

4         QUICKSORT(A, q + 1, r)

PARTITION(A, p, r)1  x ← A[r]

2  i ← p – 1

3  for j ← p to r – 1

4       do if A[j] ≤ x

5             then i ← i + 1

6                  exchange A[i] <-> A[j]

7  exchange A[i + 1] <-> A[r]

8  return i + 1

二、算法分析

快排代码(未改进):

#include <stdio.h>

#include <time.h>

#include <stdlib.h>

#include <sys/time.h>  

#include <iostream>  

using namespace std;

int k = 70;

void swap(int* p, int* q)

{
    int x;

    x = *p;

    *p = *q;

    *q = x;
}

int partition(int *a, int p, int r)

{
    int i = 0;

    int j = 0;

    int x = 0;

    i = p - 1;

    x = a[r];

    for (j = p; j < r - 1; j++)

    {

        if (a[j] <= x)

        {

            i++;

            swap(&a[i], &a[j]);
        }
    }

    swap(&a[i + 1], &a[r]);

    return i + 1;

}

void quicksort(int *a,int p,int r )

{

    int q=0;

    if (r>p)

    {

        q = partition(a, p, r);

        quicksort(a, p, q - 1);

        quicksort(a, q + 1, r);
    }
}

int main(int argc,char* argv[])

{   struct timeval start,finish;     

    double Totaltime = 0.0;   

    int a[200000] = { 0 };

    int i = 0;

    srand((unsigned)time(NULL));

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

    {

        a[i] = rand() % 1000000;

    }

    printf("随机生成的数组:\n");

    printf("\n");

    gettimeofday(&start,NULL); 

    quicksort(a,0,199999);

    gettimeofday(&finish,NULL);  

    Totaltime = finish.tv_sec - start.tv_sec + (finish.tv_usec - start.tv_usec) / 1000000.0;  

    std::cout<<"程序运行时间为:"<<Totaltime<<std::endl; 

    printf("对数组进行插入排序:\n");

    printf("\n");

    system("pause");

    return 0;
}



quicksort在递归到只有几个元素大小的数组时开始用插入排序的方法。改进的快速排序方法在期望时间=原始快排的期望时间+插入排序方法的期望时间。

这里还是要用到7.4(算法导论第7章)的分析方法。对于快排还要计算期望比较次数。因为被划分在同一个小数组k中的元素,是不会在快排里比较的。所以Xij只要计算那些i和j相差k-1个以上的元素比较就可以了。

定义一个元素集合Zij={zi,zi+1,,,,,,,,zj},定义一个指示器随机变量Xij=I{zi与zj进行了比较},E[Xij]=Pr[Xij]=Pr{zi与zj进行了比较}=Pr{zi是Zij的主元}+Pr{zj是Zij的主元}=2/(j-i+1)//因为在快排中,二者能够比较,则其中一个必是主元.快速排序的期望比较次数E[Xij]为

 

那么快排的期望时间是O(nlg(n/k)),假设优化后的快排产生的小数组大小O(k),在每个大小O(k)的小数组里使用插入排序,时间复杂度为O(k^2),总共有O(n/k)个小数组,则插入排序时间为O(nk),。那么把这些时间加起来就是O(nk+nlog(n/k))。

但是k的值并不是越大越好,当k值超过临界值后,其性能会变差。


三、算法优化(改进后)

#include <stdio.h>

#include <time.h>

#include <stdlib.h>

 

#include <sys/time.h>  

#include <iostream>  

using namespace std;

int k = 70;

void swap(int* p, int* q)

{
    int x;

    x = *p;

    *p = *q;

    *q = x;
    
}
int partition(int *a, int p, int r)

{

    int i = 0;

    int j = 0;

    int x = 0;

    i = p - 1;

    x = a[r];

    for (j = p; j < r - 1; j++)

    {

        if (a[j] <= x)

        {

            i++;

            swap(&a[i], &a[j]);
            
        }
        
    }
    swap(&a[i + 1], &a[r]);

    return i + 1;
    
}
void quicksort(int *a,int p,int r )
{

    int q=0;

    if (r-p>=k)

    {

        q = partition(a, p, r);

        quicksort(a, p, q - 1);

        quicksort(a, q + 1, r);
    }
    
}
void insertSort(int *a, int p, int r)
{    
    int i, j;

    int tmp = 0;

    for (i = p + 1; i <= r; i++)

    {

        tmp = a[i];

        j = i;

        while (a[j - 1] > tmp)

        {

            a[j] = a[j - 1];

            j--;

        }

        a[j] = tmp;

    }

}

void promote_sort(int *a, int p, int r)

{

    quicksort(a, p, r);

    insertSort(a, p, r);

}

int main(int argc,char* argv[])

{        

    struct timeval start,finish;  

    double Totaltime = 0.0;

    int a[200000] = { 0 };

    int i = 0;

    srand((unsigned)time(NULL));

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

    {

        a[i] = rand() % 1000000;

    }

    printf("随机生成的数组:\n");

    printf("\n");

    gettimeofday(&start,NULL); 

    promote_sort(a,0,199999);

    gettimeofday(&finish,NULL);  

    Totaltime = finish.tv_sec - start.tv_sec + (finish.tv_usec - start.tv_usec) / 1000000.0;  

    std::cout<<"改进后的插入快排运行时间为:"<<Totaltime<<std::endl; 

    printf("对数组进行插入快速排序:\n");

    printf("\n");

    system("pause");

    return 0;
    
}



评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

打赏作者

fullstack_lth

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

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

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

打赏作者

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

抵扣说明:

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

余额充值