1.13 排序与查找&文件重定向

1.13 排序与查找&文件重定向

1. 文件重定向

#include<iostream>
#include<cstdio>
using namespace std;

int main(){
    //从文件 data.in中读入数据到输入流中,替代了我们手动输入数据的过程,所以read.in提前就需要建好,并存入数据
    freopen("data.in", "r", stdin);

    //将输出流的数据写入文件 data.out中,也就是控制台的输出数据被写入到文件中
    freopen("data.out", "w", stdout);

    int a,b;  cin>>a>>b;
    cout<<a+b;
    return 0;
}

2. 排序

1. 冒泡排序

原理:走访未排序好的数列,一次比较两个相邻元素,如果它们的顺序错误就把它们交换过来。

走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。

冒泡排序算法的运作如下:

  1. 比较相邻的元素。如果第一个比第二个大,就交换他们两个。
  2. 对每一对相邻元素作同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数。
  3. 针对所有的元素重复以上的步骤,除了最后一个。
  4. 持续每次对越来越少的元素重复上面的步骤,直到没有任何一对数字需要比较。
#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int N=1e3;
int a[N];
int main(){
    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);

    int n; 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]){//升序排列
                int t = a[j];
                a[j] = a[j+1];
                a[j+1] = t;
            }
        }//每次冒泡结束都输出一次当前的结果 
        for(int i=1; i<=n; i++) cout<<a[i]<<" "; cout<<endl;
    }
    return 0;
}

2. 选择排序

原理:每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

和冒泡排序的区别就在于不是每次比较两个相邻元素,但是其原理和实现大同小异。

#include<iostream>
#include<cstdio>
#include<cstdlib>
using namespace std;
const int N=1e3;
int a[N];
int main(){
    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);

    int n; cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];

    //选择排序:每次选择最大(或最小)放在最前面
    for(int i=1; i<=n; i++){
        int min=i;//假设当前就是最小值
        for(int j=i; j<=n; j++){
            if(a[min]>a[j]) min=j;//升序排序,记录最小值的下标
        }
        if(min!=i){//如果最小值的下标发生变化,则交换当前值与最小值
            int temp = a[min];
            a[min] = a[i];
            a[i] = temp;
        }
    }
    for(int i=1; i<=n; i++) cout<<a[i]<<" "; cout<<endl;
    return 0;
}

3.插入排序

每步将一个待排序的记录,按其关键码值的大小插入前面已经排序的文件中适当位置上,直到全部插入完为止。

#include<iostream>
using namespace std;
const int N=1e5+10;
int n,a[N];

int main() {
    cin>>n;
    for(int i=1; i<=n; i++) cin>>a[i];
// 插入排序:将元素插入一个有序序列中
    for(int i=2; i<=n; i++){
        // [1, i-1]
        int k=i; // 当前要插入的元素
        for(int j=i-1; j>=1; j--){
            if(a[k] < a[j]) swap(a[k], a[j]), k=j;
            else break;
        }
    } 
    for(int i=1; i<=n; i++) cout<<a[i]<<" "; cout<<endl; 
    return 0;
}

4. 桶排序

桶排序其实可以看作是一个计数问题

比如:有一串数据:4 5 4 6 3 1 1 2

可以发现,数据中最小值为1,最大值为6,
那么我们可以采用对数字进行计数的方式来记录。

a[i] = n; //表示数据 i 出现的次数为 n次

那么对数据:4 5 4 6 3 1 1 2
a[1] = 2
a[2] = 1
a[3] = 1
a[4] = 2
a[5] = 1
a[6] = 1

再按照下标从小到大输出下标,每一个下标 i 的输出次数与 a[i]的值相等。
则上述数据输出的结果为:1 1 2 3 4 4 5 6

然后就发现了一个神奇的现象,数据竟然就排好序了,而且是升序排序。

如果要降序序排序,那么输出下标按从大到小,降序排序即可。

程序实现:

#include<iostream>
#include<cstdio>
using namespace std;
const int N=1e3;
int a[N];
int main(){
    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);

    int n,max=0,min=1e4; cin>>n;
    for(int i=1; i<=n; i++) {
        int x; cin>>x;
        a[x]++;    //桶排序关键,计数
        if(max<x) max=x;//最大值
        if(min>x) min=x;//最小值
    }
    for(int i=min; i<=max; i++){//用来规范数据范围
        for(int j=1; j<=a[i]; j++){
            cout<<i<<" ";
        }
    }
    return 0;
}

5. sort

#include<iostream>
#include<algorithm>
using namespace std;
const int N=1e4;
int a[N];

int main(){
    freopen("data.in", "r", stdin);
//    freopen("data.out", "w", stdout);

    int n; cin>>n;
    for(int i=0; i<n; i++) cin>>a[i];
    sort(a, a+n);//a[0]~a[n-1]
    //sort(首地址, 首地址+元素个数)

//   如果输入从1开始,那么首地址需要变化,如下
//  sort(a+1, a+1+n);// a[1]~a[n]
    return 0;
}

除了上述排序方法外还有:快速排序,归并排序,希尔排序,堆排序....

3. 查找

1. 顺序查找

其实所谓的顺序查找就是将所有可能的答案进行一次遍历,直到找到正确的答案才结束。

#include<iostream>
using namespace std;

int main(){
    int a[10]={1,2,3,4,5,6,7,8,9,0};

    //顺序查找:一个一个的查找
    int x=4;
    for(int i=0; i<10; i++){
        if(a[i]==x) {
            cout<<i<<" "<<a[i];
            break;//找到答案退出
        }
    }
    return 0;
}

2. 二分查找

二分查找是基于一段有序序列的查找算法,每一次查找是从序列的中间开始查找,所以叫二分查找。

#include<iostream>
using namespace std;

int main(){
    int a[10]={0,1,2,3,4,5,6,7,8,9};

    //二分查找:从中间开始查找
    int l=0, r=9, x=4;
    while(l<=r){
        int mid = (l+r)/2;
        if(a[mid]==x) {
            cout<<mid<<" "<<a[mid];
            break;//找到答案退出
        }else if(a[mid]<x){
            l = mid+1;//答案一定在右边
        }else if(a[mid]>x){
            r = mid-1;//答案一定在左边
        }
    }
    return 0;
}
posted @ 2021-08-21 23:34  HelloHeBin  阅读(228)  评论(0编辑  收藏  举报