快速排序(quickSort)四种经典实现

7 篇文章 0 订阅
5 篇文章 0 订阅

一、.算法分析

快速排序使用分治(Divide and conquer)策略,从序列中选取pivot ,把这个序列(list)通过这个pivot分为两个子序列(sub-lists),一个子序列中所有的元素都不大于pivot,另一个子序列中的所有元素都不小于pivot,从而确定了pivot在整个序列的位置,对每个子序列执行同样的操作,直至序列中的每个元素的最终位置都确定。

步骤为:

从数列中挑出一个元素,称为 "基准"(pivot)

  1. 重新排序数列,所有元素中比基准值小的摆放在基准前面,所有元素中比基准值大的摆在基准的后面(相同的数可以到任一边)。在这个分割结束之后,该基准就处于数列的中间位置。这个称为分割(partition)操作。
  2. 递归地(recursive)对小于基准值元素的子数列和大于基准值元素的子数列排序。

递归的最底部情形,是数列的大小是零或一,也就是已经被排序好了。虽然一直递归下去,但是这个算法总会结束,因为在每次的迭代(iteration)中,它至少会把一个元素摆到它最终的位置上。

 

二、快速排序算法性能分析。

     快速排序的平均时间复杂度为o(nlgn).空间复杂度o(1), 就地(in place)排序,不稳定的排序。

 

 

三、算法的实现。(参见《算法导论》的第7章)

本文实现4种quickSort的实现:它们的实现核心是对划分的的设计。

1.第一种:qickSort使用增量求解的方式进行划分,

在数组a[p..r] 中构建选取a[r]为pivot基准元,在子数组a[p...i...j]中,具有这样的性质:

 1)、对于 p<=k <=i, 总有a[k] <=pivot;

 2)、对于 i< k <=j  总有a[k]> pivot;

是一个循环不变式。证明不再给出。

 

2.第二种:randomizedQuickSort随机算法。

公认随机算法能够改善quickSort的平均性能。所谓,随机算法,在算法中引入随机数,使算法对象的处理具有概率上的公平性。

quickSort算法的运行好坏取决于划分的优劣,划分的形成取决于pivot基准的选择,为了使基准的选择性更具有一般性,通过一个随机数生成器来辅助pivot基准的选取。

划分方法同第一种。

3.第三种: Hoare-quickSort 算法,最初的版本的quicksort。发现其实现有一定的技巧,而且很容易出错。原算法中有一些不必要的重复交换,本实现做了一定修改。

 

4. 第四种: 是对Hoare-quickSort算法的一种改进版,用赋值代替交换,从而避免了不必要的交换。

 

下面给出quickSort算法的4中实现:

 

#include <stdio.h>
#include <stdlib.h>
#include <time.h>


void printArray(int* a, int len);
void exchange(int* a, int* b);
int getRandomNum(int a, int b);

int partition(int* a, int p, int r);
void quickSort(int* a, int p, int r);

int randomizedPartition(int* a, int p, int r);
void randomizedQuickSort(int* a, int p, int r);

int hoarePartition(int* a, int p, int r);
void hoareQuickSort(int* a, int p, int r);

int modifiedHoarePartition(int* a, int p, int r);
void modifiedHoareQuickSort(int* a, int p, int r);



int main(int argc, char* argv[])
{
    int a[] ={5, 4, 3, 2, 1, 3, 3, 3, 3, 3, 5, 6, 1};
    int len = sizeof(a)/sizeof(a[0]);

    // quickSort(a, 0, len-1);
    // randomizedQuickSort(a, 0, len-1);
    // hoareQuickSort(a, 0, len-1);
    modifiedHoareQuickSort(a, 0, len-1);

    printArray(a, len);

    return 0;
}


void printArray(int* a, int len) {
    int i;

    for(i=0; i<len; i++) {
        printf("%d\t", a[i]);
    }

    printf("\n");
}

void exchange(int* a, int* b) {
    int tmp;

    tmp = *a;
    *a = *b;
    *b = tmp;
}


int partition(int* a, int p, int r) {
    int i;
    int j;
    int pivot;

    pivot = a[r];
    i = p-1;

    for(j=p; j<r; j++) {
        if(a[j]<= pivot) {
            i++;
            exchange(a+i, a+j);
        }
    }
    exchange(a+i+1, a+r);

    return i+1;
}

//加入随机算法的partition算法
int randomizedPartition(int* a, int p, int r) {
    int i;

    /*
    srand((unsigned)time(NULL)); // init the seed of rand()
    i = rand()%(r-p) + p;
    */
    i = getRandomNum(p, r);
    exchange(&a[i], &a[r]);

    return partition(a, p, r);
}



int hoarePartition(int* a, int p, int r) {
    int i;
    int j;
    int pivot;

    pivot = a[p];
    i = p;
    j = r+1;

    while(i<j) {
        while(i<j && a[--j]>pivot);
        while(i<j && a[++i]<=pivot);

        if(i<j) {
            exchange(&a[i], &a[j]);
        }
    }

    if(i!=p) exchange(&a[i], &a[p]);


    return i;

}

int modifiedHoarePartition(int* a, int p, int r) {
    int i;
    int j;
    int pivot;

    pivot = a[p];
    i = p;
    j = r;

    while(i<j) {
        while(i<j && a[j]>pivot) j--;
        if(i<j) a[i++] = a[j];
        while(i<j && a[i]<=pivot) i++;
        if(i<j) a[j--] = a[i];
    }

    if(i!= p) a[i] = pivot;

    return i;


}

void quickSort(int* a, int p, int r) {
    int q;

    if(p<r)  {
        q = partition(a, p, r);
        quickSort(a, p, q-1);
        quickSort(a, q+1, r);
    }

}

void randomizedQuickSort(int* a, int p, int r) {
    int q;

    if(p<r) {
        q = randomizedPartition(a, p, r);
        randomizedQuickSort(a, p, q-1);
        randomizedQuickSort(a, q+1, r);
    }

}




void hoareQuickSort(int* a, int p, int r) {
    int q;

    if(p<r) {
        q = hoarePartition(a, p, r);
        hoareQuickSort(a, p, q-1);
        hoareQuickSort(a, q+1, r);
    }

}


void modifiedHoareQuickSort(int* a, int p, int r) {
    int q;

    if(p<r) {
        q = modifiedHoarePartition(a, p, r);
        modifiedHoareQuickSort(a, p, q-1);
        modifiedHoareQuickSort(a, q+1, r);
    }

}


int getRandomNum(int a, int b) {
    srand((unsigned)time(NULL)); // init the seed of rand()

    return rand()%(b-a) + a;
}


 

以上参考《算法导论》第7章。

 

  • 1
    点赞
  • 3
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
快速排序QuickSort)是一种高效的排序算法,它基于分治策略。该算法首先选择一个元素作为基准值(pivot),然后将待排序数组按照基准值分成两个子数组,一边是所有小于基准值的元素,另一边是所有大于等于基准值的元素。然后对两个子数组分别递归地进行快速排序,最后将两个子数组合并起来即可得到完整的有序数组。 以下是使用C++实现快速排序的代码: ```cpp void quickSort(vector<int>& nums, int left, int right) { if (left >= right) return; // 递归终止条件 int pivot = nums[left]; // 选择第一个元素作为基准值 int i = left, j = right; while (i < j) { // 一趟快速排序 while (i < j && nums[j] >= pivot) j--; // 从右往左找到第一个小于基准值的元素 if (i < j) nums[i++] = nums[j]; // 将该元素放入左半部分 while (i < j && nums[i] < pivot) i++; // 从左往右找到第一个大于等于基准值的元素 if (i < j) nums[j--] = nums[i]; // 将该元素放入右半部分 } nums[i] = pivot; // 将基准值放入合适的位置 quickSort(nums, left, i - 1); // 递归地对左半部分进行快速排序 quickSort(nums, i + 1, right); // 递归地对右半部分进行快速排序 } ``` 其中,`nums`表示待排序数组,`left`和`right`表示当前子数组的左右边界(初始时应为0和`nums.size()-1`)。我们首先选择第一个元素作为基准值,然后使用双指针i和j在数组中进行一趟快速排序,将小于基准值的元素放入左半部分,将大于等于基准值的元素放入右半部分。最后将基准值放入合适的位置,并递归地对左右两个子数组进行快速排序

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值