zoukankan      html  css  js  c++  java
  • 初等排序 讲义

    这里我们简述一下初等排序的学习内容:

    • 选择排序
    • 冒泡排序
    • 比较函数
    • 结构体函数

    选择排序

    (1)基本思想:每一趟从待排序的数据元素中选出最小(或最大)的一个元素,顺序排在待排序的数列的最前,直到全部待排序的数据元素排完。
    (2)排序过程:
    假设现在有 (n) 个数,他们分别是 (a_1, a_2, a_3, a_4, ……, a_n) ,我要将它们按照从小到大排序。

    • (1) 轮:我要选出最小的数作为 (a_1) ,于是我从 (2)(n) 遍历 (j) ,如果 (a_1 lt a_j) ,则交换 (a_1)(a_j) ,遍历结束后我们保证 (a_1) 是最小的数。
    • (2) 轮:我要选出次小的数作为 (a_2) ,于是我从 (3)(n) 遍历 (j) ,如果 (a_2 lt a_j) ,则交换 (a_2)(a_j) ,遍历结束后我们保证 (a_2) 是最次的数。
    • 如是循环……
      (3)选择排序代码示例:
    #include <bits/stdc++.h>
    using namespace std;
    int n, a[100];
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i ++) cin >> a[i];
        for (int i = 1; i < n; i ++)
            for (int j = i+1; j <= n; j ++)
                if (a[i] > a[j])
                    swap(a[i], a[j]);
        for (int i = 1; i <= n; i ++) cout << a[i] << " ";
        return 0;
    }
    

    这样我能保证在 (n-1) 轮比较后,我的数组能够按照从小到大的顺序排列好。这就是选择排序。
    看上去有点像排老大——“我想当老大,不服的上来比一比,比过了你就当老大”。然后排完老大排老二,排完老二排老三,如是循环……
    选择排序的时间复杂度是 (O(n^2))

    冒泡排序

    (1)基本思想:以 (n) 个人排队为例,从第 (1) 个开始,一次比较相邻的两个是否 逆序(“逆序”的意思是说:比如要按照元素从小到大排序,而此时相邻的两个元素中前者比后者大,则需要调换这两者的值),若逆序就交换两人,接着第 (2) 个和第 (3) 个比,若逆序就交换两人,接着第 (3) 个和第 (4) 比,若逆序就交换两人,……,直到 (n-1)(n) 比较,经过一轮比较后,则把最高的人排到最后,即将冒泡一样逐步冒到相应的位置。原 (n) 个人的排序就转换成 (n-1) 个人的排序问题。第二轮从第 (1) 个开始,一次比较相邻的两个人是否逆序对,若逆序就交换两人,直到 (n-1)(n) 比较。如此,进行 (n-1) 轮之后,这个数列就会变成有序的数列。
    (2)排序过程:
    假设现在有 (n) 个数,他们分别是 (a_1, a_2, a_3, a_4, ……, a_n) ,我要将它们按照从小到大排序。

    • (1) 轮:我开一个循环变量 (j)(1)(n-1) ,每次比较 (a_j)(a_{j+1}) ,如果 (a_j > a_{j+1}) ,则交换 (a_j)(a_{j+1})
      其实我这么循环是有原因的:一开始 (a_1)(a_2) 比较(如果逆序则交换)之后我能够保证 (a_2) 是前 (2) 个数中最大的;然后再拿 (a_2)(a_3) 比较(如果逆序则交换)之后我能够保证 (a_3) 是前 (3) 个数中最大的;……,最后我们拿 (a_{n-1})(a_n) 比较,其实是拿前 (n-1) 个数中的最大的和 (a_n) 比(如果逆序则交换),那么我们在第 (1) 轮结束的时候 (a_n) 就是我们数列中最大的数,并且它也恰好存储在了 (a_n) 中。
    • (2) 轮:我开一个循环变量 (j)(1)(n-2) ,每次比较 (a_j)(a_{j+1}) ,如果 (a_j > a_{j+1}) ,则交换 (a_j)(a_{j+1})
      同时,我这么操作一遍之后能够保证 (a_{n-1}) 是我们数列中次大的;
    • (3) 轮,我开一个循环变量 (j)(1)(n-3) ,每次比较 (a_j)(a_{j+1}) ,如果 (a_j > a_{j+1}) ,则交换 (a_j)(a_{j+1})
    • 如是循环……
      (3)冒泡排序代码示例:
    #include <bits/stdc++.h>
    using namespace std;
    int n, a[100];
    int main() {
        cin >> n;
        for (int i = 1; i <= n; i ++) cin >> a[i];
        for (int i = 1; i < n; i ++)
            for (int j = 1; j <= n-i; j ++)
                if (a[j] > a[j+1])
                    swap(a[j], a[j+1]);
        for (int i = 1; i <= n; i ++) cout << a[i] << " ";
        return 0;
    }
    

    这样我能保证在 (n-1) 轮比较后,我的数组能够按照从小到大的顺序排列好。这就是冒泡排序。

    比较函数和sort函数

    比较函数用于确定数组中的排序规则,比如给我一个 int a[] 数组,我可以使用 algorithm 库提供给我的 sort 函数给他排序,比如,我调用:

    sort(a, a+n);
    

    能够给数组从 a[0]a[n-1] 按从小到大的顺序进行排序。因为 sort 函数就是按照默认从小到大的顺序来给数组中的元素进行排序的。
    但是如果我想要使用 sort 函数来给数组中的元素按照从大到小的顺序排序呢?这个是用我们需要自定义一个比较函数,并且将函数名作为 sort 函数的第 (3) 个参数传递进去。
    例如,我下面定义了一个名为 cmp 的比较函数,他里面有两个参数 ab ,这个函数返回 true 说明 a 应该排在 b 前面,返回 false 说明 b 应该排在 a 后面:

    bool cmp(int a, int b) {
        return a > b;
    }
    

    然后将这个函数的名字作为参数传递给 sort 函数调用即可:

    sort(a, a+n, cmp);
    

    这样就能保证将 a[0]a[n-1] 按照从大到小排序了。

    特别的,对于结构体来说,因为结构体不知道怎么比较大小,所以需要你编写比较函数并放到 sort 函数里面去给他进行排序。

    说明:其实对于结构体来说,也有办法让它直到怎么比较大小,就是给结构体定义一个小于号( (lt) ),这种方法叫做“运算符重载”,但是运算符重载放在我们普及组初赛相对来说超纲了,所以这里就不过多的介绍“运算符重载”这个C++高级知识点了,目前的阶段是好好掌握比较函数。

  • 相关阅读:
    寄存器总结
    汇编知识积累
    windbg 配置符号路径
    UNICODE环境下读写txt文件操作
    vs2010 安装项目完成桌面快捷方式无法定位程序文件夹 解决方法
    spring源码解析之属性编辑器propertyEditor
    springboot国际化与@valid国际化支持
    No identifier specified for entity
    springboot 项目中css js 等静态资源无法访问的问题
    Git教程
  • 原文地址:https://www.cnblogs.com/zifeiynoip/p/11450537.html
Copyright © 2011-2022 走看看