王道计算机考研机试指南刷题笔记-自用4

目录

第三章 排序与查找

3.1 排序

例题3.1 排序(华科复试上机题)

①直接插入排序

②折半插入排序

③希尔排序

④冒泡排序

⑤快速排序

例题3.2 成绩排序(清华复试上机题)

例题3.3 成绩排序(清华复试上机题)

习题3.1 特殊排序(华科复试上机题)

习题3.2 整数奇偶排序(北大复试上机题)

习题3.3 小白鼠排队(北大复试上机题)


第三章 排序与查找

3.1 排序

例题3.1 排序(华科复试上机题)

排序_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • 排序这一块儿挺重要的,初试结束之后就没再看过了,经典排序算法的实现忘得差不多了,用这一题重新捡起来。
  • C++ algorithm 库中的sort函数:sort(first,last,comp) // first和last为待排序序列的起始地址arr和结束地址arr+n,comp为排序方式,默认升序。如果要降序排列或自定义排列,可以编写比较函数来实现。
  • 去年备考的笔记还在,翻出来复习一遍之后再用不同的排序方法都实现一遍。

2、解答

①直接插入排序

// 1.直接插入排序
void insertSort(int a[], int n) {
    int i, j;
    // 将第2~n个元素依次插入已排好序的队列中
    for ( i = 1 ; i < n ; i++ ) {
        int temp;
        // 只有a[i]<a[i-1](已排序好的最后一个元素)时才需要移动
        if ( a[i] < a[i - 1] ) {
            // temp暂存待排序的a[i]
            temp = a[i];
            // 所有大于temp的元素都后移一位
            for ( j = i - 1 ; a[j] > temp ; --j ) {
                a[j + 1] = a[j];
            }
            // 将待排序元素插入最终位置
            a [j + 1] = temp;
        }
    }
}

②折半插入排序

//2.折半插入排序
void insertSort2(int a[], int n) {
    int i, j, low, high, mid,temp;
    // 将第2~n个元素依次插入已排好序的队列中
    for ( i = 2; i <= n ; i++ ) {
        temp = a[i];
        // 折半查找的两个端点值
        low = 1, high = i-1;
        // while循环条件:low<=high
        while ( low <= high ) {
            mid = (low + high) / 2;
            if ( temp < a[mid] )
                high = mid-1; // 查找左半子表
            else
                low = mid+1; // 查找右半子表
        }
        for ( j = i - 1 ; j >= high + 1 ; --j ) {
            a[j + 1] = a[j];
        }
        // 将待排序元素插入最终位置
        a [high + 1] = temp;
    }
}

       

③希尔排序

//3.希尔排序
void shellSort(int a[], int n) {
    int i, j, dk;
    for ( dk = n / 2 ; dk >= 1 ; dk = dk / 2 ) { // 步长变化
        for ( i = dk + 1 ; i <= n ; i++ ) {
            // 将a[i]插入有序增量序列
            if ( a[i] < a[i - dk] ) {
                a[0] = a[i];
                // 注意循环条件
                for ( j = i - dk ; j > 0 && a[j] > a[0] ; j -= dk ) {
                    a[j + dk] = a[j];
                }
                a[j + dk] = a[0];
            }
        }
    }
}

        

④冒泡排序

//4.冒泡排序
void bubbleSort(int a[],int n){
    int i,j;
    bool flag;
    for ( i = 0 ; i < n ; i++ ) {
        // 标志本趟冒泡是否发生交换
        flag = false;
        for ( j = n-1 ; j > i ; j-- ) {
            int temp;
            if ( a[j] < a[j-1] ) {
                temp = a[j];
                a[j] = a[j-1];
                a[j-1] = temp;
                flag = true;
             }
        }
        // 本次冒泡没有发生交换,说明已有序
        if (!flag)
            return;
    }
}

⑤快速排序

        一个大坑:写的时候把pivot写成了a[pivot],结果怎么都不对,自己来回对了几遍也没发现问题……

//5.快速排序
int Partition(int a[], int low, int high) {
    // 选取第一个元素作为枢轴元素
    int pivot = a[low];
    while (low < high) {
        // high所指向的元素大于等于枢轴元素,--high
        while (low < high && a[high] >= pivot ) --high;
        // 比枢轴元素小的移到左边
        a[low] = a[high];
        // low所指向的元素小于等于枢轴元素,++low
        while (low < high && a[low] <= pivot ) ++low;
        // 比枢轴元素大的移到右边
        a[high] = a[low];
    }
    // 跳出循环时low=high,枢轴元素存在到a[high]
    a[low] = pivot;
    return low;
}

void quickSort(int a[], int low, int high) {
    if ( low < high ) {
        int pivotpos = Partition(a, low, high);
        quickSort(a, low, pivotpos - 1);
        quickSort(a, pivotpos + 1, high);
    }
}

例题3.2 成绩排序(清华大学复试上机题)

成绩排序_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • 处理多个学生学号和成绩的时候,发现直接输入不行。看了解析发现这里是对结构体进行排序,需要先将学生抽象为一个结构体,用C++更方便。
  • 排序的要求:
  • 成绩相等:比较学号,从小到大排序
  • 成绩不等:比较成绩,从小到大排序
  • 排序利用C++ alogrithm库中的sort函数可以实现,只需要编写自定义排序函数comp,特别注意comp函数的写法。

2、源代码

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

// 定义学生结构体
struct Student {
    int id;
    int score;
};

// 自定义比较函数
bool comp (Student a, Student b) {
    // 成绩相等比较学号
    if (a.score == b.score) 
        return a.id < b.id;
    else 
        // 成绩不等比较成绩
        return a.score < b.score;
}

int main() {
    int n;
    scanf("%d\n", &n);
    Student arr[n];
    for (int i = 0 ; i < n ; i++) {
        scanf("%d %d\n", &arr[i].id, &arr[i].score);
    }
    sort(arr, arr + n, comp);
    for (int i = 0 ; i < n ; i++) {
        printf("%d %d\n", arr[i].id, arr[i].score);
    }
    return 0;
}

例题3.3 成绩排序(清华大学复试上机题)

成绩排序_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • 按照上一题一样的思路哐哐写,写了两个自定义排序函数,用户输入0调用降序,输入1调用升序。
  • 不出意外没通过,看了其他人解法的评论区发现sort排序是不稳定排序,而题目要求相同成绩按照先录入者排序在前的规则处理。
  • stable_sort(first,last,cmp) 函数可以实现稳定排序。
  • 由于学生信息中包含姓名,所以输入输出选用C++ 的cin和cout会更方便。

2、总结

  • 书上给的解法是在学生结构体中多定义了一个int型id属性,输入学生信息时依次id赋值,比较成绩时相同成绩再继续比较id,id小的即先录入的,符合题目要求。
  • 也可以自己编写稳定的排序算法(比如冒泡排序)来实现。

3、源代码

// version 1 : stable_sort()实现
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

// 定义学生结构体
struct Student {
    string name;
    int score;
};

// 升序或降序
int flag;

// 自定义排序函数
bool cmp(Student a, Student b) {
    if (flag == 0) {
        return a.score > b.score;
    } else
        return a.score < b.score;
}


int main() {
    int n;
    while ( cin >> n ) {
        cin >> flag;
        Student s[n];
        for ( int i = 0 ; i < n ; i++) {
            cin >> s[i].name >> s[i].score;
        }
        stable_sort(s, s + n, cmp);
        for ( int i = 0 ; i < n ; i++) {
            cout << s[i].name << " " << s[i].score << endl;
        }
    }
}
// version 2 : 给Student结构体添加id属性实现稳定排序
#include <iostream>
#include <cstdio>
#include <algorithm>
using namespace std;

// 定义学生结构体
struct Student {
    string name;
    int score;
    int id;  // 标识录入的先后顺序
};

// 升序或降序
int flag;

// 自定义排序函数
bool cmp(Student a, Student b) {
    if (flag == 0) {
        // 分数相等,id小的在前
        if (a.score == b.score) {
            return a.id < b.id;
        } else {
            // 分数不等,按分数降序排列
            return a.score > b.score;
        }
    } else {
        if (a.score == b.score) {
            return a.id < b.id;
        } else {
            // 分数不等,按分数升序排列
            return a.score < b.score;
        }
    }
}


int main() {
    int n;
    while ( cin >> n ) {
        cin >> flag;
        Student s[n];
        for ( int i = 0 ; i < n ; i++) {
            cin >> s[i].name >> s[i].score;
            s[i].id=i; // 给id赋值
        }
        stable_sort(s, s + n, cmp);
        for ( int i = 0 ; i < n ; i++) {
            cout << s[i].name << " " << s[i].score << endl;
        }
    }
}

习题3.1 特殊排序(华科复试上机题)

特殊排序_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • sort函数对输入的数进行排序,先输出排序后的最后一个元素(即最大值),再依次输出前n个元素。
  • 我想复杂了,我想的是先找到最大值,再把最大值从数组中删掉,对剩下的元素用一次sort函数。

2、源代码

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

#define N 1010

int a[N];

int main() {
    int n;
    int i;
    cin >> n;
    for (i = 0 ; i < n ; i++) {
        cin >> a[i];
    }
    // 对数组a升序排列
    sort(a,a+n);
    // 输出最后一个元素(即最大值)
    cout << a[n-1] << endl;
    // 判断是否有剩下的数
    if( n==1 ) {
        cout << "-1" << endl;
    } else {
        for (i = 0 ; i < n-1 ; i++) {
            cout << a[i] << " "; // 依次输入前n-1个有序元素
        }
        cout << endl;
    }

}

习题3.2 整数奇偶排序(北大复试上机题)

整数奇偶排序_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • 定义两个奇偶数组,输入时判断奇偶性,存入对应数组
  • 对奇数组降序排列,偶数组升序排列,一次AC。
#include <iostream>
#include <algorithm>
using namespace std;

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

int main() {
    int a[10];
    int even[10],odd[10];
    int i,j=0,k=0;
    for (i = 0 ; i < 10 ; i++) {
        cin >> a[i];
        if (a[i]%2 == 0) {
            even[j++] = a[i]; // a[i]是偶数,存入even
        } else {
            odd[k++] = a[i]; // a[i]是奇数,存入odd
        }
    }
    sort(odd,odd+k,cmp); // 对奇数降序排列
    for(i = 0 ; i < k ; i++) {
        cout << odd[i] << " ";
    }
    sort(even,even+j);  // 对偶数升序排列
    for(i = 0 ; i < j ; i++) {
        cout << even[i] << " ";
    }
    cout << endl;    
}

2、其他方法

  ① 先把所有的按从小到大排序,然后遍历两次数组。第一遍从后往前,遇到奇数就输出;第二遍从前往后,遇到偶数就输出。(很巧妙,通过从后往前遍历实现奇数的降序排列) 

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

int main() {
    int a[10];
    while(cin>>a[0]>>a[1]>>a[2]>>a[3]>>a[4]>>a[5]>>a[6]>>a[7]>>a[8]>>a[9]) {
        // 对数组a升序排序
        sort(a,a+10);
        // 从后往前遍历排序好的a数组,遇到奇数就输出
        for(int i = 9 ; i >= 0 ; --i) {
            if (a[i]%2 == 1) 
                cout << a[i]<< " ";
        }
        // 从前往后遍历排序好的a数组,遇到偶数就输出
        for(int i = 0 ; i < 10 ; ++i) {
            if (a[i]%2 == 0) 
                cout << a[i]<< " ";
        }
        cout << endl;
    }
}

  ② 在cmp函数中书写比较逻辑:传入两个整型参数a,b

  • a、b都是奇数:降序排列
  • a、b都是偶数:升序排列
  • a、b一个奇数一个偶数:奇数排在偶数前面(最后一个return没看懂,私信了原作者,等一个回复orz)
#include <iostream>
#include <algorithm>
using namespace std;

bool cmp (int a,int b) {
    if ( a%2==1 && b%2==1 ) // a、b都是奇数,降序排列
        return a > b;
    else if ( a%2==0 && b%2==0 )  // a、b都是偶数,升序排列
        return a < b ;
    else 
        return a%2 > b%2;  // 这里没看懂orz
}

int main() {
    int a[10];
    for (int i = 0 ; i < 10 ; i++) {
        cin >> a[i];
    }
    sort(a,a+10,cmp);
    for (int i = 0 ; i < 10 ; i++) {
        cout << a[i] << " ";
    }
    cout << endl;
}

习题3.3 小白鼠排队(北大复试上机题)

小白鼠排队_牛客题霸_牛客网 (nowcoder.com)

1、思路

  • 与例题3.2类似,定义老鼠结构体,存储重量和帽子颜色两个属性。
  • 编写自定义比较函数cmp,按重量降序排列。比较简单

2、源代码

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

struct Mouse { // 定义老鼠结构体
    int weight;
    string color;
};

bool cmp(Mouse a, Mouse b) { // 定义cmp比较函数,按重量降序排列
    return a.weight > b.weight;
}

int main() {
    int n;
    cin >> n;
    Mouse m[n];
    for (int i = 0 ; i < n ; i++) {
        cin >> m[i].weight >> m[i].color;
    }
    sort(m, m + n, cmp);
    for (int i = 0 ; i < n ; i++ ) {
        cout << m[i].color << endl;
    }
}

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值