zoukankan      html  css  js  c++  java
  • PAT数列排序

    19考研结束了

    。。

    还有11天PAT甲

    题目链接:http://lx.lanqiao.cn/problem.page?gpid=T52

    题目大意:训练排序

    解题思路:

    方法一:

    直接用C++里的sort函数,

    1  #include<algorithm>
    2  using namespace std;

    这两句缺一不可。sort函数的排序不仅仅只用了快速排序,还结合了插入排序和堆排序。然后sort函数原型有三个参数:

    1.要排序的数组的起始地址。

    2.结束的地址(最后一位要排序的地址)

    3.排序的方法。如果省略是默认了从小到大排序。如果从大到小就要自己写https://blog.csdn.net/latte_z/article/details/17049479 、  https://www.cnblogs.com/jjzzx/p/5122381.html

    代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int main()
     5 {
     6     int n;
     7     int a[500];
     8     scanf("%d", &n);
     9     for(int i = 0; i < n; i ++)
    10         scanf("%d", &a[i]);
    11     sort(a, a + n);
    12     for(int i = 0; i < n - 1; i ++)
    13         printf("%d ", a[i]);
    14     printf("%d
    ", a[n - 1]);
    15 }

    方法二:

    冒泡排序(大一学过,发现没学明白,搞了两三天)

    参考博客

    冒泡就是每一次都使得max/min去他应该去的位置

    但是按照之前琐碎的记忆(n-1趟,j从i开始,for两次,一次n-1,一次n什么的),写了一个错误的代码,如下

     1 /*
     2 冒泡序算法
     3 测试样例
     4 6
     5 2 3 8 5 1 5
     6 */
     7 
     8 #include<cstdio>
     9 #include<algorithm>
    10 using namespace std;
    11 int main()
    12 {
    13     int w = 0;
    14     int n;
    15     int a[500];
    16     scanf("%d", &n);
    17     for(int i = 0; i < n; i ++)
    18         scanf("%d", &a[i]);
    19         
    20 //这是错的方法
    21     for(int i = 0; i < n - 1; i ++){
    22         for(int j = i; j < n -1; j ++){
    23             if(a[j] > a[j + 1]){
    24                 int temp = a[j];
    25                 a[j] = a[j + 1];
    26                 a[j + 1] = temp;
    27             }
    28         }
    29         printf("%d: ", w++);//为了调试找错
    30         for(int k = 0; k < n; k ++)
    31             printf("%d ", a[k]);
    32             printf("
    
    ");
    33     }
    34     
    35     printf("
    ");
    36 }

    百思不得其解,最后发现root(根本)所在,——————(这里用升序来推翻它)

    第一个for——比如1,2,3仨数字,我a[0]和a[1]比,再和a[2]比,OK!a[1]再和a[2]比,最后a[2]就不用就谁比较了,因为上一步已经比较过了。所以这里是n-1趟,n-1个数字找到位置了,最后一个就不必麻烦了

    第二个for——我i的取值是从i到n-2因为,如果到了n-1,下一步a[j]和a[j + 1]比,会因为a[j]为0,而把a[n - 1]和a[n]调换,最后第一回合,把原数字都给改变了,变成0了。好了!再来说里面循环的事,我a[j]和a[j + 1]比较,做的仅仅是把最大或最小放到了他应去的位置,并不能保证第一位是最小的还是最大,所以我第二次i == 1的时候,直接 j 从 i 开始往后搞,默认了a[0]是最小的了,所以记住代码真坑时间精力也坑自己

    那么正解应该是这样的

     先考虑升序,有  种分析方法:

    1.大的往下沉:

    关键代码是两个for,这次外层for是从0到n-2还是共n趟,因为n个数字,n - 1次就可以确定n - 1个正确位置,最后一个(没进入趟的)不用管

    接下来内层for注意是要从0开始,因为

    1  if(a[j] > a[j + 1])

    每次都是相邻两个比较,大的往后去,第一趟结束,最后侧就是最大的了,这样下一次就不需要管它了,直接 j 循环到他前面的那个就好了,比如 i == 1(从0开始),我只需要执行到 j == n - 3就行,下面的

    1  if(a[j] > a[j + 1])

    使得 a[n - 3] 和 a[n - 2]进行比较,大的会落在a[n - 2]的位置,正好倒数第二个。

    完整代码:

     1 #include<cstdio>
     2 int main()
     3 {
     4     int n;
     5     int a[500];
     6     scanf("%d", &n);
     7     for(int i = 0; i < n; i ++)
     8         scanf("%d", &a[i]);
     9     for(int i = 0; i < n - 1; i ++)
    10         for(int j = 0; j < n - 1 - i; j ++)
    11         {
    12             if(a[j] > a[j + 1])
    13             {
    14                 int temp = a[j];
    15                 a[j] = a[j + 1];
    16                 a[j + 1] = temp;
    17             }
    18         }
    19     for(int k = 0; k < n - 1; k ++)
    20     printf("%d ", a[k]);
    21         printf("%d
    ", a[n - 1]);
    22     
    23 }

    (降序就是改成 “<”,小的往下去了)

    2.小的往上冒泡(上浮):

    这里有点说法,其实如果说要你升序,小的往上,那不能用刚才的代码,因为那个是大的下沉的,改成“<”是降序,所以要另一种思维

    这里外层不再说了,内层是 j 从 i + 1 到最后一个n - 1,每次一比较 a[i] 和 a[j],因为 i 是外层,每次不会变,从0开始遍历,那么内层做的就是,你找来一群人,让他们排好队,手里人民币只要比我少的,我直接用 我的所有人民币 和 你的所有的人民币 换, 结束后我手里是这群人堆里最少的人民币数(有这样的好事?  

    但是经过了这么大折腾,仅仅找到了一个最小的,现在已经放到了第一个位置,后面还是乱序的,甚至不是乱序,也要按照规则,一个一个比较。

    完整代码:

     1 #include<cstdio>
     2 #include<algorithm>
     3 using namespace std;
     4 int main()
     5 {
     6     int n;
     7     int a[500];
     8     scanf("%d", &n);
     9     for(int i = 0; i < n; i ++)
    10         scanf("%d", &a[i]);
    11     for(int i = 0; i < n - 1; i ++)
    12     {
    13         for(int j = i + 1; j < n; j ++)
    14         {  //小的上浮(升序)    <是大的上浮(降序)
    15             if(a[i] > a[j])
    16             {
    17                 int temp = a[i];
    18                 a[i] = a[j];
    19                 a[j] = temp;
    20             }
    21         }
    22         for(int k = 0; k < n; k ++)
    23             printf("%d ", a[k]);
    24         printf("
    
    ");
    25     }
    26     for(int k = 0; k < n - 1; k ++)
    27         printf("%d ", a[k]);
    28     printf("%d
    ", a[n - 1]);
    29 
    30 }

    至于冒泡排序稳定性,这个比较好https://bbs.csdn.net/topics/370123385https://zhidao.baidu.com/question/279325341.html

    ***************************************************只学了皮毛,后续逐渐补充*****************************************

  • 相关阅读:
    2016个人测试1(待续。。。)
    bzoj2548[Cstc2002]灭鼠行动
    noip2013 积木大赛
    noip2013 火柴排队
    Noip2000 T3 单词接龙
    noip2017爆炸记——题解&总结&反省(普及组+提高组)
    【2017.10.26-】后缀数组学习笔记
    20171002清北
    【搜索党】卡时技巧
    【noip】noip201503求和(题解可能不完美,但绝对详细)
  • 原文地址:https://www.cnblogs.com/gerjcs/p/10394699.html
Copyright © 2011-2022 走看看