• 机试笔记5--排序


    一.使用sort来进行排序,它的时间复杂度是nlogn,所以能在1s内处理大概30w的数据

        cmp(typename x,typename y)中是可以对x,y进行更改的,并不会影响到数组中的数,这也极大增加了cmp的适用性。

        题型一.成绩排序(要求稳定)

                输入任意(用户,成绩)序列,可以获得成绩从高到低或从低到高的排列,相同成绩都按先录入排列在前的规则处理。

                分析:该题的考点是稳定排序,而sort排序是不稳定排序,解决的方法有两个,一是使用stable_sort函数,它的使用方法和sort一样。另一种方法是给每一个输入加一个递增的下标,然后进行二级排序,当值相同时,下标小的排在前面。

            方法一:

               在编写这个代码的过程中遇到了使用stable_sort报错的问题,发现是由于sort只能给int,char进行排序。解决这个问题也很简单,只需要更改cmp函数就可以

    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef struct Student
    {
        string name;
        int score;
    }Student;
    bool downCmp(Student x,Student y)
    {
        return x.score>y.score;
    }
    bool upCmp(Student x,Student y)
    {
        return x.score<y.score;
    }
    int main()
    {
        int n,flag;
        cin >> n;
        cin >> flag;
        vector<Student> stu;
        Student s;
        for(int i=0;i<n;i++){
          cin >> s.name >> s.score;
          stu.push_back(s);
        }
        int len = stu.size();
        if(flag==0){
          stable_sort(stu.begin(),stu.end(),downCmp);
        }
        else stable_sort(stu.begin(),stu.end(),upCmp);
        for(int i=0;i<stu.size();i++){
          cout << stu[i].name << " "<<stu[i].score<<endl;
        }
        return 0;
    }

          方法二:二级排序,在结构体中添加了一个变量num用于记录每一个变量的先后顺序。

    #include <iostream>
    #include <algorithm>
    #include <vector>
    using namespace std;
    typedef struct Student
    {
        string name;
        int score;
        int num;
    }Student;
    bool downCmp(Student x,Student y)
    {
        if(x.score > y.score)
            return true;
        else if(x.score==y.score)
            return x.num<y.num;
        else return false;
            
    }
    bool upCmp(Student x,Student y)
    {
        if(x.score < y.score)
            return true;
        else if(x.score==y.score)
            return x.num<y.num;
        else return false;
    }
    int main()
    {
        int n,flag;
        cin >> n;
        cin >> flag;
        vector<Student> stu;
        Student s;
        for(int i=0;i<n;i++){
          cin >> s.name >> s.score;
          s.num=i;
          stu.push_back(s);
        }
        int len = stu.size();
        if(flag==0){
          sort(stu.begin(),stu.end(),downCmp);
        }
        else sort(stu.begin(),stu.end(),upCmp);
        for(int i=0;i<stu.size();i++){
          cout << stu[i].name << " "<<stu[i].score<<endl;
        }
        return 0;
    }

     题型三.输入n个数进行排序,要求先按奇偶后按从小到大的顺序排序。核心还是在cmp函数上。

    #include <iostream>
    #include <algorithm>
    using namespace std;
    bool cmp(int x,int y)
    {
        if(x%2>y%2)
            return true;
        else if(x%2==y%2)
            return x<y;
        else return false;
    }
    int main()
    {
        int n;
        cin >> n;
        int num;
        vector<int> arr;
        for(int i=0;i<n;i++){
          cin >> num;
          arr.push_back(num);
        }
        sort(arr.begin(),arr.end(),cmp);
        for(int i=0;i<n;i++){
          cout <<arr[i]<<" ";
        }
        cout << endl;
        return 0;
    }

    题型四.字符串排序

    编写一个程序,将输入字符串中的字符按如下规则排序(一个测试用例可能包含多组数据,请注意处理)。

    规则 1 :英文字母从 A 到 Z 排列,不区分大小写。

    如,输入: Type 输出: epTy

    规则 2 :同一个英文字母的大小写同时存在时,按照输入顺序排列。

    如,输入: BabA 输出: aABb

    规则 3 :非英文字母的其它字符保持原来的位置。

    如,输入: By?e 输出: Be?y

    分析:规则一只要在cmp中全部改成大写进行排序就可以

               规则二使用stable_sort就可以

               规则三只要不对非字母进行排序就可以

    #include <iostream>
    #include <algorithm>
    #include <cstring>
    using namespace std;
    bool cmp(char x,char y)
    {
        if('a'<=x&&x<='z') 
            x-='a'-'A';
        if('a'<=y&&y<='z')
            y-='a'-'A';
        return x<y;
    }
    int main()
    {
        char str[1005];
        char t[1005];
        while(gets(str)){
            int j=0;
          for(int i=0;i<strlen(str);i++){
            if(('a'<=str[i]&& str[i]<='z')||('A'<=str[i]&& str[i]<='Z'))
                t[j++]=str[i];
          }
          stable_sort(t,t+strlen(t),cmp);
            int c=0;
          for(int i=0;i<strlen(str);i++){
            if(('a'<=str[i]&& str[i]<='z')||
               ('A'<=str[i]&& str[i]<='Z'))
                str[i] = t[c++]; 
          }
           cout << str<<endl;
        }
        return 0;
    }

    先输入你要输入的字符串的个数。然后换行输入该组字符串。每个字符串以回车结束,每个字符串少于一百个字符。 如果在输入过程中输入的一个字符串为“stop”,也结束输入。 然后将这输入的该组字符串按每个字符串的长度,由小到大排序,按排序结果输出字符串。

    这里要注意的是在cin >> n和getline(cin,arr)之间要加一个getchar,因为cin之后输入缓冲区还有一个' '

    整个过程如下

    运行到 cin>>n,你输入一个数并按回车,cin把这个数给n并换行,此时输入缓冲区还有一个' ',如果此时getline的话,getline会把这个换行符吞掉并换成''给arr[1],所以arr[1]实际上是个空字符串。排序后这个空字符串会占第一行,所以就会出现隔一行输出排序后结果且少一个字符串的情况。

    #include <bits/stdc++.h>
    using namespace std;
    
    bool cmp(string x,string y)
    {
        return x.size() <y.size();
    }
    int main()
    {
        int n;
    
        while(cin >> n){
            getchar();
          string arr[n];
        int i=0;
          for(;i<n;i++){
            getline(cin,arr[i]);
            if(arr[i]=="stop"){
                break;
            }
          }
          sort(arr,arr+i,cmp);
          for(int j=0;j<i;j++){
            cout << arr[j] <<endl;
          }
        }
        return 0;
    }

    一些特殊的情况

      1.数据量很大,有几百万,这时候,nlogn的sort就无法满足要求了,如果待排数据的大小范围不是太大的话,可以使用简单的计数排序。时间复杂度为O(n)

      2.找出数组中第K大的元素,可以利用快速排序中的分区算法

        

    int findK(int K,int a[],int start,int end)
    {
        int pos;
        pos = partition(a,start,end);
        if(K>pos+1)
            return findK(K,a,pos+1,end);
        else if(K<pos+1)
            return findK(K,a,start,pos-1);
        else
            return a[pos];
    }

               

  • 相关阅读:
    try catch使用示例
    doxgen生成chm文档和乱码解决方法
    MFC中MessageBox()用法
    UML聚合与组合
    C#网络编程
    单元测试(NUnit)
    Autohotkey
    .NET中的并行
    System.Environment类的使用
    一键VHD
  • 原文地址:https://www.cnblogs.com/Sunqingyi/p/12601135.html
Copyright © 2020-2023  润新知