算法初步——排序

简单选择排序

  • 令i从0到n-1枚举,进行n趟操作,每趟从A[i,n]中选择最小的元素 ,算法复杂度为O(n^2)
    /*
        选择排序
        思路:令i从0到n-1枚举,进行n趟操作,每趟从A[i,n]中选择最小的元素 
    */
    
    void selectSort(int A[], int n) {
        for(int i=0; i<n; ++i) {
            int k = i;                        // 记录最小元素 
            for(int j=i+1; j<n; ++j) {        // 从A[i,n]中选择最小的元素
                if(a[j] < a[k])    k = j;
            }
            
            int temp = a[i];            // 交换 
            a[i] = a[k];
            a[k] = temp; 
        }
    }

 

直接插入排序

  • 假设某一趟时,序列A的前i-1个元素A[1]~A[i-1]已经有序,然后从范围[1,i-1]中寻找某个位置j ,使得插入后仍然有序,算法复杂度为O(n^2)

    /*
        直接插入排序
        思路: 假设某一趟时,序列A的前i-1个元素A[1]~A[i-1]已经有序,
               然后从范围[1,i-1]中寻找某个位置j ,使得插入后仍然有序 
    */
    
    void insertSort(int A[], int n) {
        for(int i=1; i<n; ++i) {        // 进行n-1趟排序 
            int temp=A[i], j=i;            // 从前往后遍历
            while(j>0 && temp<A[j-1]) {
                A[j] = A[j-1];            // 后移 
                j--;
            } 
            A[j] = temp; 
        }
    } 

     

 

sort函数的应用

  • 使用时必须加上头文件  #include <algorithm>  和   using namespace std; 
  •  函数原型

    // sort(首元素的地址(必填),尾元素地址的下一个地址,比较函数(非必填))
    sort(a, a+6);
  • 如何实现比较函数cmp
    • 若比较函数不填,则默认按照从小到大的顺序排序,如果想要从大到小来排序,则要使用比较函数cmp
      bool cmp(int a, int b) {
          return a > b;    // 可以理解为当 a > b 时把 a 放前面 
      }  
    • 结构体数组的排序
      • 一级排序,按照 x 从大到小排序
        struct node {    // 结构体定义 
            int x, y;
        } ssd[10]; 
        bool cmp(node a, node b) {            // 一级排序 
            // 将ssd数组按照x从大到小排序 
            return a.x > b.x;
        } 
      • 二级排序,先按照 x 从大到小排序,但当 x 相等的情况下,按照 y 的大小来排序
        bool cmp(node a, node b) {            // 二级排序 
            // 将ssd数组先按照 x 从大到小排序,
            // 但当 x 相等的情况下,按照 y 的大小来排序
            if(a.x != b.x)    return a.x > b.x;
            else return a.y > b.y;
        }
    • 容器的排序
      • 在 STL 标准容器中,只有 vector、string、deque 是可以使用 sort 的。这是因为 set、map 这种容器是用红黑树实现的,元素本身有序
      • vector 的排序: sort(vi.begin(), vi.end()); // 对 vi 进行排序 
      • string 的排序: sort(str, str+3); // 对 str 进行排序        

    • 实例:对学生进行排序
      • 如果两个学生分数不相同,那么分数高的排在前面
      • 否则,将姓名字典序小的排在前面
        struct Student {
            char name[10];        // 姓名
            char id[10];        // 准考证号
            int score;            // 分数
            int rank;            // 排名 
        } stu[10010]; 
        bool cmp(Student a, Student b) {    // 二级排序 
            if(a.score != b.score)    return a.score > b.score;
            else return (strcmp(a.name, b.name) < 0);
        }      
  • 排名的实现
    • 规则一般是:分数不相同的排名不同,分数相同的排名相同但占用一个排位
      • 在数组排序完成后,先将数组的第一个个体(假设数组下标从0开始)的排名记为1
      • 然后遍历剩余个体
        • 如果当前个体的分数等于上一个个体的分数,那么当前个体的排名等于上一个个体的排名
        • 否则,当前个体的排名等于数组下标加一
          stu[0].rank = 1;
          for(int i=1; i<n; ++i) {
              if(stu[i].score == stu[i-1].score) {
                  stu[i].rank = stu[i-1].rank;
              } else {
                  stu[i].rank = i+1;
              }
          } 

 

PAT A1025 PAT Ranking       

  •  题意:在 n 个考场有若干数量的考生。现在给出各个考场中考生的准考证号与分数,要求将所有考生按分数从高到低排序,并顺序输出所有考生的准考证号、排名、考场号、考场排名
  • 思路:
    • 按考场读入各考生的信息,并对当前读入的考生进行排序,将排名写入结构体中 
    • 对所有考生进行排序
    • 按顺序一边计算总排名,一边输出所有考生的信息
       1 #include <cstdio>
       2 #include <cstring>
       3 #include <algorithm>
       4 #include <cmath>
       5 using namespace std;
       6 
       7 struct Student {
       8     char id[15];            // 准考证号
       9     int score;                // 分数
      10     int location_number;    // 考场号
      11     int local_rank;            // 考场排名 
      12 } stu[30010]; 
      13 
      14 // 定义排序方法 
      15 bool cmp(Student a, Student b) {
      16     // 先按分数从大到小排序 
      17     if(a.score != b.score)    return a.score > b.score;
      18     else return (strcmp(a.id, b.id) < 0);    // 后按准考证号排序 
      19 } 
      20 
      21 int main() {
      22     int n, k, num=0;    // n 考场数 k 考场人数 num 总人数
      23     scanf("%d", &n);     // 输入考场数 
      24     
      25     // 按考场输入并排名 
      26     for(int i=1; i<=n; ++i) {
      27         scanf("%d", &k);    // 输入考场人数
      28         for(int j=1; j<=k; ++j) {    // 输入考生信息 
      29             scanf("%s %d", stu[num].id, &stu[num].score);
      30             stu[num].location_number = i;
      31             num++;            // 考生数量 +1 
      32         } 
      33         sort(stu+num-k, stu+num, cmp);    // 考场排序 
      34         stu[num-k].local_rank = 1;                        // 考场内排名 
      35         for(int j=num-k+1; j<num; ++j) {
      36             if(stu[j].score == stu[j-1].score) {
      37                 stu[j].local_rank = stu[j-1].local_rank;
      38             } else {
      39                 stu[j].local_rank = j - (num-k) +1;
      40             }
      41         } 
      42     }
      43     // 所有考生排名并输出信息 
      44     sort(stu, stu+num, cmp);
      45     int rank = 1;                // 记录排名 
      46     printf("%d\n", num);        // 边计算总排名,边输出信息 
      47     printf("%s %d %d %d\n", stu[0].id, rank, stu[0].location_number, stu[0].local_rank); 
      48     for(int i=1; i<num; ++i) {
      49         if(stu[i].score != stu[i-1].score) {
      50             rank = i+1;
      51         }
      52         printf("%s %d %d %d\n", stu[i].id, rank, stu[i].location_number, stu[i].local_rank); 
      53     } 
      54 
      55     return 0;
      56 }

       

 

qsort 函数的应用

  c语言中没有预置的sort函数,如果在c语言中,要调用sort函数,就需要使用c语言自有的qsort函数,其头文件为stdlib.h。

函数原型

1 void __cdecl qsort (void *base,size_t num,size_t width
2             ,int (__cdecl *comp)(const void *,const void*))  

 

输入参数:

  base:待排序数组

  num:数组元素的个数

  width:每一个元素所占存储空间的大小

  comp:自定义,决定排序的顺序

 

以下是 qsort 的几种用法(升序排列)

1. 对一维数组排序:

1 #define ElemType double    // 可以为 char、int、float、double 
2 // 对一维数组排序 
3 int cmp1(const void* a, const void* b) {
4     return *((ElemType*)a) > *((ElemType*)b) ? 1:-1;
5 }

 

2. 对字符串排序:

1 // 对字符串排序
2 int cmp2(const void* a, const void* b) {
3     return strcmp((char*)a, (char*)b);
4 }

 

3. 按结构体中多个关键字排序(多级排序):

 1 // 对结构体排序
 2 struct node {
 3     double data;
 4     int other;
 5 } s[100];
 6 // 先按 data 从小到大排序
 7 // 若 data 相等,按 other 从小到大排序 
 8 int cmp3(const void* a, const void* b) {
 9     struct node* c = (node*)a;
10     struct node* d = (node*)b;
11     if(c->data != d->data) {
12         return (c->data > d->data) ? 1 : -1;
13     } else {
14         return c->other - d->other;
15     }
16 }

 

posted @ 2018-01-06 14:31  Just_for_Myself  阅读(396)  评论(0编辑  收藏  举报