• 算法导论学习笔记(五):快速排序


    201382

    15:41

       

    快速排序是一种最坏情况运行时间为O(n*n),虽然这个最坏情况运行时间比较差,但快速排序通常都是用于排序的最

    佳的实用选择,这是因为其平均性能相当好:期望的运行时间为O(nlgn),且O(nlgn)记号中隐含的常数因子很小。另

    外,它还能够进行就地排序。

       

    快速排序和合并排序一样,采用的都是分治思想。快排中利用该思想解决步骤为:

    1、先从数组中取出一个数作为基数,基数的选择对排序效率的影响很大

    2、分区,将比这个基数小的数全部放到它的左边,比基数大的数全部放到其右边

    3、对左右两个区间重复第二步,直到每个区间只有一个数

       

    下面结合代码来进一步理解快速排序。算法导论上一开始给出的基数选择就是直接选择待排序数组中最后一个元素作

    为基数,即对于数组a[N],以a[N-1]作为基数。以一般情况来讨论,当我们要进行排序的数组为a[p...r]时,选择a[r]

    基数,然后将这个序列分为3部分,a[p...q-1]a[q] a[q+1, r],其中a[p...q-1]的元素都是小于基数的,a[q]就是基

    数,a[q+1, r]的元素都大于基数。其实现代码如下:

    [cpp] view plaincopyprint?

    • int partition (int a[], int p, int r)  
    • {  
    •     int i = p - 1;  
    •     for (int j = p; j < r; j++)  
    •     {  
    •         if (a[j] < a[r])  
    •         {  
    •             swap (a[++i], a[j]);  
    •         }  
    •     }  
    •     swap (a[++i], a[r]);  
    •     return i;  
    • }  

    该函数的执行过程如下图:

    这个函数最后返回的便是q,接下来我们便要对a[p...q-1]a[q+1, r]重复上述步骤,直到只剩下一个元素。代码如下:

    [cpp] view plaincopyprint?

    • void quick_sort (int a[], int p, int r)  
    • {  
    •     if (p < r)  
    •     {  
    •         int q = partition (a, p, r);  
    •         quick_sort (a, p, q - 1);  
    •         quick_sort (a, q + 1, r);  
    •     }  
    • }  

    最后附上我自己的一个完整的代码,可以直接运行测试运行结果:

    [cpp] view plaincopyprint?

    • #include<iostream>  
    • using namespace std;  
    •   
    • void display (int a[], int n);  
    • void swap (int& n, int& m);  
    • int partition (int a[], int p, int r);  
    • void quick_sort (int a[], int p, int r);  
    •   
    • int main()  
    • {  
    •     int a[100];  
    •     int n;  
    •     while (cin >> n)  
    •     {  
    •         for (int i = 0; i < n; i++)  
    •             cin >> a[i];  
    •         quick_sort (a, 0, n - 1);  
    •         display (a, n);  
    •     }  
    •     return 0;  
    • }  
    •   
    • void display (int a[], int n)  
    • {  
    •     for (int i = 0; i < n; i++)  
    •         cout << a[i] << " ";  
    •     cout << endl;  
    • }  
    •   
    • void swap (int& n, int& m)  
    • {  
    •     int temp;  
    •     temp = n;  
    •     n = m;  
    •     m = temp;  
    • }  
    •   
    • int partition (int a[], int p, int r)  
    • {  
    •     int i = p - 1;  
    •     for (int j = p; j < r; j++)  
    •     {  
    •         if (a[j] < a[r])  
    •         {  
    •             swap (a[++i], a[j]);  
    •         }  
    •     }  
    •     swap (a[++i], a[r]);  
    •     return i;  
    • }  
    •   
    • void quick_sort (int a[], int p, int r)  
    • {  
    •     if (p < r)  
    •     {  
    •         int q = partition (a, p, r);  
    •         quick_sort (a, p, q - 1);  
    •         quick_sort (a, q + 1, r);  
    •     }  
    • }  

    算法导论书上在最后还提供了几个改进的版本,如随机化版本,三数取中等,这些改进的版本基本都是在对基数选择

    方法上进行改进的。有兴趣的朋友可以自己试试!

  • 相关阅读:
    PHP mysqli扩展库 预处理技术
    libevent入门(1)
    你的项目需要升级成64bit程序吗?
    [敏捷个人]个人知识管理
    [转]职业规划中的“我想要”和“我需要”
    《领导力》读书笔记
    http 传输原理及格式
    转载:Fiddler 教程
    Nginx 配置文件详解
    Wireshark
  • 原文地址:https://www.cnblogs.com/fuyou/p/3233284.html
Copyright © 2020-2023  润新知