c/c++蓝桥杯经典编程题100道(9)数组排序

news/2025/2/13 17:29:57/

数组排序

->返回c/c++蓝桥杯经典编程题100道-目录


目录

数组排序

一、题型解释

二、例题问题描述

三、C语言实现

解法1:冒泡排序(难度★)

解法2:选择排序(难度★)

解法3:快速排序(难度★★★)

四、C++实现

解法1:使用STL的sort函数(难度★☆)

解法2:自定义排序规则(难度★★)

解法3:归并排序(难度★★★)

五、总结对比表


一、题型解释

数组排序是将数组元素按特定顺序(升序、降序或自定义规则)重新排列的操作。常见题型:

  1. 基础排序:将数组按升序或降序排列(如 [3,1,4] → [1,3,4])。

  2. 稳定排序:相同元素的相对顺序不变(如按姓名排序后,同分学生的顺序不变)。

  3. 条件排序:按自定义规则排序(如按绝对值、奇偶性等)。

  4. 部分排序:仅排序数组的一部分(如前k个元素)。


二、例题问题描述

例题1:输入数组 [5, 2, 9, 1, 5],输出升序排列结果 [1, 2, 5, 5, 9]
例题2:输入数组 [-3, 1, -5, 4],按绝对值升序排列输出 [1, -3, 4, -5]
例题3:输入数组 [7, 3, 8, 5],输出降序排列结果 [8, 7, 5, 3]


三、C语言实现

解法1:冒泡排序(难度★)

通俗解释

  • 像水中的气泡,每次将最大的元素“冒”到数组末尾。

c

#include <stdio.h>void bubbleSort(int arr[], int n) {// 外层循环:控制排序轮数(每一轮确定一个最大值的位置)for (int i = 0; i < n-1; i++) { // 内层循环:比较相邻元素并交换for (int j = 0; j < n-1-i; j++) { if (arr[j] > arr[j+1]) { // 交换元素(大的往后“冒”)int temp = arr[j];arr[j] = arr[j+1];arr[j+1] = temp;}}}
}int main() {int arr[] = {5, 2, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);bubbleSort(arr, n);for (int i = 0; i < n; i++) {printf("%d ", arr[i]); // 输出 1 2 5 5 9}return 0;
}

代码逻辑

  1. 外层循环:共进行 n-1 轮(每轮确定一个最大值的位置)。

  2. 内层循环:每轮比较相邻元素,若前大后小则交换。

  3. 优化:第 i 轮时,末尾 i 个元素已有序,无需再比较。

  4. 时间复杂度:O(n²)(最坏情况)。


解法2:选择排序(难度★)

通俗解释

  • 每次从剩余元素中选最小的,放到已排序序列末尾。

c

#include <stdio.h>void selectionSort(int arr[], int n) {for (int i = 0; i < n-1; i++) { int minIndex = i; // 假设当前元素是最小值// 遍历剩余元素,找到实际最小值的位置for (int j = i+1; j < n; j++) { if (arr[j] < arr[minIndex]) {minIndex = j; // 更新最小值位置}}// 将最小值与当前位置交换int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}
}int main() {int arr[] = {5, 2, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);selectionSort(arr, n);for (int i = 0; i < n; i++) {printf("%d ", arr[i]); // 输出 1 2 5 5 9}return 0;
}

代码逻辑

  1. 外层循环:遍历数组,每轮确定一个最小值的位置。

  2. 内层循环:在未排序部分中找到最小值的位置 minIndex

  3. 交换操作:将最小值与当前未排序部分的第一个元素交换。

  4. 时间复杂度:O(n²)。


解法3:快速排序(难度★★★)

通俗解释

  • 像“分而治之”,选一个基准值,小的放左边,大的放右边,递归处理左右子数组。

c

#include <stdio.h>// 分区函数:将数组分为左右两部分,返回基准值的位置
int partition(int arr[], int low, int high) {int pivot = arr[high]; // 选最后一个元素作为基准值int i = low - 1;       // 指向比基准值小的区域的末尾for (int j = low; j < high; j++) {if (arr[j] < pivot) {i++;// 交换元素,将小的值移到左边int temp = arr[i];arr[i] = arr[j];arr[j] = temp;}}// 将基准值放到正确位置int temp = arr[i+1];arr[i+1] = arr[high];arr[high] = temp;return i + 1;
}// 递归排序函数
void quickSort(int arr[], int low, int high) {if (low < high) {int pi = partition(arr, low, high); // 获取基准值位置quickSort(arr, low, pi - 1);        // 排序左半部分quickSort(arr, pi + 1, high);       // 排序右半部分}
}int main() {int arr[] = {5, 2, 9, 1, 5};int n = sizeof(arr) / sizeof(arr[0]);quickSort(arr, 0, n-1);for (int i = 0; i < n; i++) {printf("%d ", arr[i]); // 输出 1 2 5 5 9}return 0;
}

代码逻辑

  1. 分区函数

    • 选择基准值 pivot(通常选最后一个元素)。

    • 遍历数组,将小于 pivot 的元素移到左侧。

    • 最后将 pivot 放到中间位置。

  2. 递归排序

    • 对基准值左侧和右侧的子数组递归调用快速排序。

  3. 时间复杂度:平均 O(n log n),最坏 O(n²)。


四、C++实现

解法1:使用STL的sort函数(难度★☆)

通俗解释

  • 直接调用C++标准库的排序函数,一行代码完成排序。

cpp

#include <iostream>
#include <algorithm> // 包含sort函数
#include <vector>
using namespace std;int main() {vector<int> vec = {5, 2, 9, 1, 5};sort(vec.begin(), vec.end()); // 默认升序排序for (int num : vec) {cout << num << " "; // 输出 1 2 5 5 9}return 0;
}

代码逻辑

  1. sort函数

    • 参数1:起始迭代器(vec.begin())。

    • 参数2:结束迭代器(vec.end())。

    • 默认按升序排序,底层实现为快速排序的优化版本(IntroSort)。

  2. 时间复杂度:O(n log n)。


解法2:自定义排序规则(难度★★)

通俗解释

  • 按绝对值排序或降序排序,需自定义比较函数。

cpp

#include <iostream>
#include <algorithm>
#include <vector>
using namespace std;// 自定义比较函数:按绝对值升序
bool compareAbs(int a, int b) {return abs(a) < abs(b);
}int main() {vector<int> vec = {-3, 1, -5, 4};sort(vec.begin(), vec.end(), compareAbs); // 传入自定义比较函数for (int num : vec) {cout << num << " "; // 输出 1 -3 4 -5}return 0;
}

代码逻辑

  1. 比较函数

    • 若 compare(a, b) 返回 true,则 a 排在 b 前面。

    • 此处按绝对值升序排列。

  2. 函数传递:将函数名 compareAbs 作为参数传递给 sort


解法3:归并排序(难度★★★)

通俗解释

  • 将数组分成两半,分别排序后合并。

cpp

#include <iostream>
#include <vector>
using namespace std;// 合并两个有序数组
void merge(vector<int>& arr, int left, int mid, int right) {vector<int> temp(right - left + 1);int i = left, j = mid + 1, k = 0;// 比较两个子数组的元素,依次放入临时数组while (i <= mid && j <= right) {if (arr[i] <= arr[j]) {temp[k++] = arr[i++];} else {temp[k++] = arr[j++];}}// 将剩余元素复制到临时数组while (i <= mid) temp[k++] = arr[i++];while (j <= right) temp[k++] = arr[j++];// 将临时数组拷贝回原数组for (int p = 0; p < k; p++) {arr[left + p] = temp[p];}
}// 递归排序函数
void mergeSort(vector<int>& arr, int left, int right) {if (left >= right) return;int mid = left + (right - left) / 2;mergeSort(arr, left, mid);      // 排序左半部分mergeSort(arr, mid + 1, right); // 排序右半部分merge(arr, left, mid, right);   // 合并两部分
}int main() {vector<int> vec = {5, 2, 9, 1, 5};mergeSort(vec, 0, vec.size() - 1);for (int num : vec) {cout << num << " "; // 输出 1 2 5 5 9}return 0;
}

代码逻辑

  1. 分治思想

    • 递归将数组分成两半,直到每个子数组只有一个元素。

    • 合并两个有序子数组。

  2. 合并操作

    • 创建临时数组存储合并结果。

    • 比较两个子数组的元素,按序放入临时数组。

  3. 时间复杂度:O(n log n)。


五、总结对比表

方法时间复杂度空间复杂度优点缺点
冒泡排序O(n²)O(1)简单直观效率低,仅适合小数据
选择排序O(n²)O(1)简单,交换次数少效率低
快速排序O(n log n) 平均O(log n)高效,适合大数据最坏情况O(n²)
STL sortO(n log n)O(log n)极简代码,高效依赖STL库
归并排序O(n log n)O(n)稳定排序,适合链表需要额外空间

->返回c/c++蓝桥杯经典编程题100道-目录


http://www.ppmy.cn/news/1570644.html

相关文章

AtCoder Beginner Contest 392(A-G)题解

A-B&#xff1a;略 C&#xff1a;可能题意比较绕&#xff0c;第i个答案就是穿着i这个号码&#xff08;也就是Q[j] i,这个时候j这个位置&#xff09;&#xff0c;看向的那个人的号码&#xff08;也就是P[j]) 代码&#xff1a; void solve() {int n;cin >> n;vi p(n 1…

Qt:Qt Creator项目创建

目录 认识Qt Creator Qt Creator概览 使用Qt Creator新建项目 选择项目模板 选择项目路径 选择构建系统 填写类信息设置界面 选择语言和翻译文件 选择Qt套件 选择版本控制系统 最终效果 认识Qt Creator Qt Creator概览 从开始菜单或者快捷方式打开Qt Creator集成开…

10vue3实战-----实现登录的基本功能

10vue3实战-----实现登录的基本功能 1.基本页面的搭建2.账号登录的验证规则配置3.点击登录按钮4.表单的校验5.账号的登录逻辑和登录状态保存6.定义IAccount对象类型 1.基本页面的搭建 大概需要搭建成这样子的页面: 具体的搭建界面就不多讲。各个项目都有自己的登录界面&#…

maven-依托管理

依赖配置 依赖: 之当前项目运行所需要的jar包,一个项目可以引入多个依赖 依赖传递 依赖具有传递性 直接依赖: 在当前项目中通过依赖配置建立的依赖关系 间接依赖: 被依赖的资源如果依赖其他资源, 当前项目间接依赖其他资源 如果A不想要B依赖的 x 资源, 就在A依赖B的标签内加…

NUMA 配置对 Redis 使用的影响:提升性能的秘密武器

NUMA 配置对 Redis 使用的影响:提升性能的秘密武器 在高性能数据库部署中,Redis 已成为不少企业的缓存与消息队列首选。然而,在大规模服务器上运行 Redis 时,如果不注意底层硬件架构,性能就可能大打折扣。今天,我们就来聊聊 NUMA(Non-Uniform Memory Access,非统一内存…

洛谷P8742 [蓝桥杯 2021 省 AB] 砝码称重(dp初始)

归纳蓝桥杯的这道题总结了一定对于dp的看法&#xff0c;虽然还没看到y总的动态规划&#xff0c;自己搜了搜上学期算法中学到的01背包问题。 首先动态规划问题最重要的是状态转移方程&#xff0c;将问题抽象成数学问题&#xff0c;列出方程就可以得解。 #include<cstdio> …

334递增的三元子序列贪心算法(思路解析+源码)

文章目录 题目思路解析源码总结题目 思路解析 有两种解法:解法一:动态规划(利用dp找到数组最长递增序列长度,判断是否大于3即可)本题不适用,因为时间复杂度为O(n^2),超时。 解法二:贪心算法:解法如上图,题目要求长度为三,设置第一个元素为长度1的值,是指长度二的…

ZooKeeper作为注册中心有什么问题? ZooKeeper作为注册中心,海量服务同时重启有什么问题?

目录 ZooKeeper作为注册中心存在的问题 性能瓶颈 一致性保证 复杂性 扩展性 单点故障 数据模型限制 社区和生态 安全性 总结 ZooKeeper作为注册中心,海量服务同时重启有的问题 1. ZooKeeper集群压力剧增 2. ZooKeeper Leader节点压力 3. 会话和临时节点管理 4.…