算法导论值快速排序

来源:互联网 发布:淘宝宝贝描述低 编辑:程序博客网 时间:2024/05/17 08:13

    今天和大家一起讨论快速排序,对于包含n个数的输入数组来说,快速排序是一种最坏情况时间复杂度为o(n * n)的排序算法。虽然最坏情况时间复杂度很差,但是快速排序通常是实际排序应用中最好的选择,因为它的平均性能非常好;它的期望时间复杂度为o(n lgn),而且o(n lgn)中隐含的常数因子非常小。另外,它还能进行原址排序,甚至在虚存环境中也能很好的工作。

     快速排序的描述:

            与归并排序一样,快速排序也使用了分治思想,下面是对一个典型的子数组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]进行排序。

下面则分别实现quicksort.h和quicksort.c

#ifndef _QUICKSORT_H_#define _QUICKSORT_H_#define N 10//接口声明void Quicksort(int *data,int p,int r);int Partition(int *data,int p,int r);void print_array(int *data,int n);#endif


对于接口的实现:

#include <stdio.h>#include <stdlib.h>#include "quicksort.h"static void swap(int *a,int *b){    int temp = 0;    temp = *a;    *a = *b;    *b = temp;}void Quicksort(int *data,int p,int r){    int q = 0;    if(p < r){        q = Partition(data,p,r);        Quicksort(data,p,q - 1);        Quicksort(data,q + 1,r);    }}int Partition(int *data,int p,int r){    int i = p - 1;    int x = data[r];    int j = 0;    for(j = p;j <= r - 1;++j){        if(data[j] < x){            i = i + 1;            swap(&data[i],&data[j]);        }    }    swap(&data[i + 1],&data[r]);    return i + 1;}void print_array(int *data,int n){    int  i = 0;    for(i = 0;i < n;++i){        printf("%5d",data[i]);    }    printf("\n");}

主程序:

#include <stdio.h>#include <stdlib.h>#include "quicksort.h"int main(int argc ,char **argv){    int data[N];    int i = 0;    srand(time(0));    for(i = 0;i < N;++i){        data[i] = rand() % 100;    }     printf("排序前:\n");    print_array(data,N);    Quicksort(data,0,N - 1);    printf("排序后:\n");    print_array(data,N);        return 0;}

程序执行结果:

快速排序的性能分析:
    快速排序的运行时间依赖于划分是否平衡,而平衡与否又依赖于用于划分的元素。如果划分是平衡的,那么快速排序算法性能与归并排序一样。如果划分是不平衡的,那么快速排序的性能就接近于插入排序了。

    最坏情况划分:当划分产生的两个子问题分别包含了n - 1个元素和0个元素时,快速排序的最坏情况发生了。不妨假设算法的每一次递归调用都出现了这种不平衡划分。划分操作的时间复杂度是o(n)。由于对一个大小为0的数组进行递归调用会直接返回,因此T(0) = O(1),于是算法的运行时间的递归式可以表示为:

     T(n)= T(n - 1)+T(0)+ o(n)= T(n - 1)+o(n)

利用代入法可以直接得到递归式T(n)= o(n * n)

    最好情况分析:在可能的最平衡的划分中,Partition得到的两个子问题的规模都不大于n / 2,这是因为其中一个子问题的规模为[n / 2],则另一个子问题的规模为[n / 2] - 1。在这种情况下,排序的性能非常好,此时,算法运行时间的递归式为;

    T(n) = 2T(n / 2)+ o(n)

根据定理,上述递归式的解为T(n) = o(n lgn)。

1 0