快速排序

算法思想

  在数组中选取一个基准元素,之后调整数组的顺序,基准元素的前部全部小于等于该元素,后部全部大于该元素。然后,递归的对前部和后部分别使用以上算法。所以该算法的重点在选取基准元素和调整顺序两个方面。
  如果选取的基准元素在调整后的数组中正好处在中间,递归的层数最少,算法的效率将达到最高。因此基准元素的选取对该算法的时间复杂度影响很大。选取基准元素最简单的方法就是将数组的第一个元素当作基准元素。
  这种方法虽然简单快速,但是如果需要排序的数组是一个事先排好序的 n n n个元素的数组,那么算法将会递归 n n n层,时间复杂度为 n 2 n^2 n2。为了弥补该缺陷,可以分别从数组的前部、中部和后部分别选取一个元素,将三个元素的中位数作为基准元素。使用该方法后,面对事先排号的数组可将时间复杂度降低到 n log ⁡ 2 n n\log_2n nlog2n
  选取基准元素还有一种靠运气的方法,那就是随机选取该数组中的某个元素作为基准元素。具体实现方法就是用随机数除余数组长度得到随机基准元素的下标,根据下标找到基准元素。
  调整顺序的大概思想是:用两个指针从数组两侧向中间扫描,后部指针找到一个小于等于基准元素的元素就停止,前部指针找到一个大于基准元素的元素就停止,然后将两个指针指向的元素进行交换,然后继续扫描直到两个指针相遇,最后把基准元素放到中间。

时间复杂度

  根据递推的关系可得出推算公式:
T ( n ) = { 1 + n + 2 T ( n 2 ) n ≥ 2 0 n = 1 T(n)=\left\{ \begin{array}{lrl} 1+n+2T(\frac{n}{2})&&n\geq2\\ 0&&n=1 \end{array} \right. T(n)={1+n+2T(2n)0n2n=1
   1 1 1是选取基准元素的时间, n n n是整理数组的时间, 2 T ( n 2 ) 2T(\frac{n}{2}) 2T(2n)是前部和后部两个数组所需的时间。最终计算得出: T ( n ) ∈ Θ ( n log ⁡ 2 n ) T(n)\in\Theta(n\log_{2}n) T(n)Θ(nlog2n)
  将数组第一个元素作为基准元素测试结果
将数组第一个元素作为基准元素测试结果
  将数组前部、中部和后部三个元素的中位数作为基准元素测试结果
将数组前部、中部和后部三个元素的中位数作为基准元素测试结果
  随机选取该数组中的某个元素作为基准元素测试结果
随机选取该数组中的某个元素作为基准元素测试结果

测试代码

将数组第一个元素作为基准元素

#include <iostream>
using namespace std;
typedef int element;
void quick_base(element *s,element *e){///传入指向数组前部元素和后部元素的指针
    if(e-s>0){
        element m = *s;///获取基准元素
        element *i = s;///小元素指针
        element *j = e;///大元素指针
        while(j>i){
            while(*j>m&&j>i){///j指向的元素大于基准元素
                j--;///指针前移
            }
            *i = *j;///此时j指向的元素小于等于基准元素
            while(*i<=m&&j>i){///i指向的元素小于等于基准元素
                i++;///指针后移
            }
            *j = *i;///此时i指向的元素大于基准元素
        }///指针重叠时退出
        *i = m;
        quick_base(s,i-1);///对基准元素前的进行快排
        quick_base(i+1,e);///对基准元素后的进行快排
    }
}
void quick(element *s,size_t n){///传入数组和数组长度
    quick_base(s,s+n-1);
}
int main(){
    element test[] = {
        41,467,334,500,169,724,478,358,962,464,
        705,145,281,827,961,491,995,942,827,436,
        391,604,902,153,292,382,421,716,718,895,
        447,726,771,538,869,912,667,299,35,894,
        703,811,322,333,673,664,141,711,253,868,
        547,644,662,757,37,859,723,741,529,778,
        316,35,190,842,288,106,40,942,264,648,
        446,805,890,729,370,350,6,101,393,548,
        629,623,84,954,756,840,966,376,931,308,
        944,439,626,323,537,538,118,82,929,541,
    };
    quick(test,sizeof(test)/sizeof(element));
    for(size_t i=0;i<sizeof(test)/sizeof(element);i++){
        cout << test[i] << endl;
    }
    return 0;
}

将数组前部、中部和后部三个元素的中位数作为基准元素

#include <iostream>
using namespace std;
typedef int element;
void quick_base(element *s,element *e){///传入指向数组前部元素和后部元素的指针
    if(e-s>0){
        element m;///获取基准元素
        element *k = s+(size_t)(e-s+1)/2;
        if(*k<*s){
            if(*k<*e){
                if(*s<*e){///中位数在前面
                    m = *s;
                }else{///中位数在后面
                    m = *e;
                    *e = *s;
                }
            }else{///中位数在中间
                m = *k;
                *k = *s;
            }
        }else{
            if(*k<*e){///中位数在中间
                 m = *k;
                 *k = *s;
            }else{
                if(*s<*e){///中位数在后面
                    m = *e;
                    *e = *s;
                }else{///中位数在前面
                    m = *s;
                }
            }
        }
        element *i = s;///小元素指针
        element *j = e;///大元素指针
        while(j>i){
            while(*j>m&&j>i){///j指向的元素大于基准元素
                j--;///指针前移
            }
            *i = *j;///此时j指向的元素小于等于基准元素
            while(*i<=m&&j>i){///i指向的元素小于等于基准元素
                i++;///指针后移
            }
            *j = *i;///此时i指向的元素大于基准元素
        }///指针重叠时退出
        *i = m;
        quick_base(s,i-1);///对基准元素前的进行快排
        quick_base(i+1,e);///对基准元素后的进行快排
    }
}
void quick(element *s,size_t n){///传入数组和数组长度
    quick_base(s,s+n-1);
}
int main(){
    element test[] = {
        41,467,334,500,169,724,478,358,962,464,
        705,145,281,827,961,491,995,942,827,436,
        391,604,902,153,292,382,421,716,718,895,
        447,726,771,538,869,912,667,299,35,894,
        703,811,322,333,673,664,141,711,253,868,
        547,644,662,757,37,859,723,741,529,778,
        316,35,190,842,288,106,40,942,264,648,
        446,805,890,729,370,350,6,101,393,548,
        629,623,84,954,756,840,966,376,931,308,
        944,439,626,323,537,538,118,82,929,541,
    };
    quick(test,sizeof(test)/sizeof(element));
    for(size_t i=0;i<sizeof(test)/sizeof(element);i++){
        cout << test[i] << endl;
    }
    return 0;
}

随机选取该数组中的某个元素作为基准元素

#include <iostream>
#include <random>
using namespace std;
typedef int element;
void quick_base(element *s,element *e){///传入指向数组前部元素和后部元素的指针
    if(e-s>0){
        element m;///获取基准元素
        element *k = s+(rand()%(size_t)(e-s+1));
        m = *k;
        *k = *s;
        element *i = s;///小元素指针
        element *j = e;///大元素指针
        while(j>i){
            while(*j>m&&j>i){///j指向的元素大于基准元素
                j--;///指针前移
            }
            *i = *j;///此时j指向的元素小于等于基准元素
            while(*i<=m&&j>i){///i指向的元素小于等于基准元素
                i++;///指针后移
            }
            *j = *i;///此时i指向的元素大于基准元素
        }///指针重叠时退出
        *i = m;
        quick_base(s,i-1);///对基准元素前的进行快排
        quick_base(i+1,e);///对基准元素后的进行快排
    }
}
void quick(element *s,size_t n){///传入数组和数组长度
    quick_base(s,s+n-1);
}
int main(){
    element test[] = {
        41,467,334,500,169,724,478,358,962,464,
        705,145,281,827,961,491,995,942,827,436,
        391,604,902,153,292,382,421,716,718,895,
        447,726,771,538,869,912,667,299,35,894,
        703,811,322,333,673,664,141,711,253,868,
        547,644,662,757,37,859,723,741,529,778,
        316,35,190,842,288,106,40,942,264,648,
        446,805,890,729,370,350,6,101,393,548,
        629,623,84,954,756,840,966,376,931,308,
        944,439,626,323,537,538,118,82,929,541,
    };
    quick(test,sizeof(test)/sizeof(element));
    for(size_t i=0;i<sizeof(test)/sizeof(element);i++){
        cout << test[i] << endl;
    }
    return 0;
}
#include <iostream>
using namespace std;
typedef int element;
void quick_base(element *s, element *e){
    if(e - s > 0){
        element n = *s, *i = s - 1, *j = e + 1;
        while(true){
            while(*++i < n);
            while(*--j > n);
            if(i < j) swap(*i, *j);
            else break;
        }
        quick_base(s, j);
        quick_base(j+1, e);
    }
}
void quick(element *s, size_t n){
    quick_base(s, s + n - 1);
}
int main(){
    element test[] = {
        41,467,334,500,169,724,478,358,962,464,
        705,145,281,827,961,491,995,942,827,436,
        391,604,902,153,292,382,421,716,718,895,
        447,726,771,538,869,912,667,299,35,894,
        703,811,322,333,673,664,141,711,253,868,
        547,644,662,757,37,859,723,741,529,778,
        316,35,190,842,288,106,40,942,264,648,
        446,805,890,729,370,350,6,101,393,548,
        629,623,84,954,756,840,966,376,931,308,
        944,439,626,323,537,538,118,82,929,541,
    };
    quick(test,sizeof(test)/sizeof(element));
    for(size_t i=0;i<sizeof(test)/sizeof(element);i++){
        cout << test[i] << endl;
    }
    return 0;
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论
神速百度SEO排名优化器主要为广大站长提供网站排名优化功能。可以按百度和(google)的规则快速提升指定关键词的排名。 神速百度SEO排名优化软件特点: 1、最容易收录的是.html的静态页面; 2、网页内容中关键词的密度和突出性(包括Title、DeScription和Keyword,还有正文中关键词的密度); 3、网站结构(目录的结构); 4、更新频率; 5、内容的价值(主要看是否是原创); 6、外链的价值; 神速百度SEO排名优化软件功能: 1、您可以指定几个您网站内容相关的关键词,软件可以自动通过这些关键词搜索到与您网站内容相符的文章。并下载。 2、用这些文章自动生成网页,并按随机而合理的密度插入您指定的关键词,自动配置好网页中的Title、DeScription和Keyword,插入关键词的网页和原文件已经不同,所以,内容接近原创,更容易得到百度的信任。并按指定的间隔上传生成的网页,建议每10小时上传一次。 3、定时更新上传优化的网页,增强网站的活跃性,使百度收录您网站内容的频率更快,网站排名迅速上升。 4、自动生成网站地图,也就是您所知道的sitemap.xml文件,但我们的软件会给它自动随机生成一个文件名,这样,就不容易被百度抓到规律K站了。上传网页自动更新网站地图文件。在百度站长平台提交网站地图文件后,百度会自动更新您的网页列表。 5、自动生成优化网页的列表,使优化网页的内链更合理。 6、自动交换友情链接,自动形成友情链接的联盟。您的网址将会被成千上万个网站做反向链接。网站权重迅速上升。 用以上的方法,可以迅速提升您的网站排名,根据难度不同,理论上,排到第一页只是时间问题。 注意:生成的优化网页与您制作的网页是分开的,不会影响您正常网页的内容,优化的目的是提升网站在搜索引擎中的权重,权重高了,您的正常内容自然就会排到前面。

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值