快排-荷兰国旗

举报
兔老大 发表于 2021/04/20 00:33:53 2021/04/20
【摘要】 在使用partition-exchange排序算法时,如快速排序算法,我们会遇到一些问题,比如重复元素太多,降低了效率,在每次递归中,左边部分是空的(没有元素比关键元素小),而右边部分只能一个一个递减移动。结果导致耗费了二次方时间来排序相等元素。这时我们可以多分一个区,即,小于区,等于区,大于区。(传统快排为小于区和大于区)   下面我们通过一个经典例题来练习这...

在使用partition-exchange排序算法时,如快速排序算法,我们会遇到一些问题,比如重复元素太多,降低了效率,在每次递归中,左边部分是空的(没有元素比关键元素小),而右边部分只能一个一个递减移动。结果导致耗费了二次方时间来排序相等元素。这时我们可以多分一个区,即,小于区,等于区,大于区。(传统快排为小于区和大于区)

 

下面我们通过一个经典例题来练习这种思想。

荷兰国旗问题

”荷兰国旗难题“是计算机科学中的一个程序难题,它是由Edsger Dijkstra提出的。荷兰国旗是由红、白、蓝三色组成的。

      

  现在有若干个红、白、蓝三种颜色的球随机排列成一条直线。现在我们的任务是把这些球按照红、白、蓝排序。

样例输入


  
  1. 3
  2. BBRRWBWRRR
  3. RRRWWRWRB
  4. RBRW

样例输出


  
  1. RRRRRWWBBB
  2. RRRRRWWWB
  3. RRWB

思路:

现在我们的思路就是把未排序时前部和后部分别排在数组的前面和后面,那么中部自然就排好了。

设置两个标志位head指向数组开头,tail指向数组末尾,now从头开始遍历:

(1)如果遍历到的位置为1,那么它一定是属于前部,于是就和head交换值,然后head++,now++;

(2)如果遍历到的位置为2,说明属于中部,now++;

(3)如果遍历到的位置为3,说明属于后部,于是就和tail交换值,然而,如果此时交换后now指向的值属于前部,那么就执行(1),tail--;

废话不多说,上代码。


  
  1. #include<iostream>
  2. #include<algorithm>
  3. using namespace std;
  4. const int maxn = 100 + 5;
  5. int n;
  6. string str;
  7. int main(){
  8. cin>>n;
  9. while(n--){
  10. cin>>str;
  11. int len=str.size();
  12. int now=0,ans=0;
  13. int head=0,tail=len-1;
  14. while(now<=tail){
  15. if(str[now]=='R'){
  16. swap(str[head],str[now]);
  17. head++;
  18. now++;
  19. }
  20. else if(str[now]=='W'){
  21. now++;
  22. }
  23. else{
  24. swap(str[now],str[tail]);
  25. tail--;
  26. }
  27. }
  28. cout<<str<<endl;
  29. }return 0;
  30. }

其实只要解题的话统计三个数量就好了,但是分三区的思想一定要有。

快排分三区以后降低了递归规模,避免了最差情况,性能得到改进。

文章来源: fantianzuo.blog.csdn.net,作者:兔老大RabbitMQ,版权归原作者所有,如需转载,请联系作者。

原文链接:fantianzuo.blog.csdn.net/article/details/81772701

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。