首页 > 其他分享 >快速排序——AcWing785.快速排序

快速排序——AcWing785.快速排序

时间:2024-06-06 12:29:24浏览次数:21  
标签:sort 递归 int quick 数组 AcWing785 排序 快速

AcWing785.快速排序

题目描述

785. 快速排序 - AcWing题库

运行代码

#include <iostream>
#include <algorithm>
using namespace std;
const int N = 1e6+6;
int q[N];
void quick_sort(int q[], int l, int r)
{
    if (l >= r) return;
    int m = l + r >> 1;//>>1是位运算,等价于除以2
    nth_element(q + l, q + m, q + r);//nth_element用于快速选择中位数
    quick_sort(q, l, m);
    quick_sort(q, m + 1, r);
}

int main()
{
    int n;
    cin>>n;
    for (int i = 0; i < n; i ++ ) 
    cin>>q[i];
    quick_sort(q, 0, n);
    for (int i = 0; i < n; i ++ )
    cout<<q[i]<<" ";
    return 0;
}

代码思路

通常的快速排序算法会选择一个"pivot"(基准元素),然后将数组分为两部分:一部分是小于基准的元素,另一部分是大于基准的元素。选择使用std::nth_element函数来直接找到分区中的中位数(或确切地说,是第m个元素,其中m = (l + r) / 2),并将这个元素放到正确的位置,从而达到部分排序的目的。这种方法相较于传统的选取首个元素或随机选取元素作为基准,可能在某些数据分布下有更好的性能表现。

代码解析

  1. #include指令和命名空间: 引入必要的头文件<iostream><algorithm>,并使用std命名空间。常量定义: const int N = 1e6+6; 定义了一个足够大的数组大小,用于存放至多10^6个整数。

  2. quick_sort函数: 实现了快速排序的递归逻辑。

    • 输入参数: 整型数组的起始指针q, 左边界索引l, 右边界索引r
    • 基础情况: 当左边界等于或大于右边界时,递归结束。
    • 选择中位数: 使用nth_element将数组的中位数放到正确的位置。这一步代替了传统快速排序中选择基准元素的过程。
    • 递归调用: 分别对中位数左边和右边的子序列进行递归排序。
  3. main函数:读取数组: 从标准输入读取整数n,表示数组长度,然后读取n个整数到数组q中。排序数组: 调用quick_sort函数对数组进行排序。输出结果: 将排序后的数组元素输出到标准输出。

改进空间

  1. 避免全局变量:尽量不要使用全局变量,特别是数组q[N]。这会影响代码的可重用性和模块化。可以将数组作为参数传递给quick_sort函数,同时考虑使用std::vector<int>来自动管理内存,这样可以更灵活地处理不同大小的数据集。

  2. 异常处理和输入验证:增加对输入的验证,例如检查n是否在合理范围内,防止数组越界。同时,可以考虑加入异常处理机制,提升程序的健壮性。

  3. 优化递归调用:虽然nth_element的使用简化了代码,但直接在快速排序中使用可能不是最高效的,因为它不提供两边的分割点,可能导致递归深度较大。传统快速排序中选择枢轴的方式(如三数取中法)可能在多数情况下提供更好的性能。

  4. 尾递归优化:虽然C++标准并未规定编译器必须执行尾递归优化,但在递归调用中,可以考虑调整逻辑,使其更接近尾递归形式,尽管现代编译器对于递归深度的优化已经做得很好,但良好的编程习惯仍值得提倡。

  5. 使用迭代而非递归(可选):对于非常大的数据集,递归可能导致栈溢出。虽然这不是常见的问题,但作为一种优化手段,可以考虑将递归逻辑转换为循环迭代,使用栈来手动管理递归状态。

  6. 添加函数注释和文档:代码的可读性和可维护性可以通过添加函数注释和总体说明来提升,使得其他阅读者更容易理解代码逻辑。

改进代码

#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
void quick_sort(vector<int>& nums, int l, int r) {
    if (l >= r) return;
    int mid = l + (r - l) / 2;
    nth_element(nums.begin() + l, nums.begin() + mid, nums.begin() + r + 1);
    quick_sort(nums, l, mid);
    quick_sort(nums, mid + 1, r);
}
int main() {
    int n;
    cin >> n;
    vector<int> nums(n);
    for (int i = 0; i < n; i++) {
        cin >> nums[i];
    }
    quick_sort(nums, 0, n - 1);
    for (const auto& num : nums) {
        cout << num << " ";
    }
    return 0;
}

使用vector<int>替代全局数组,并对输入数据进行了封装,提高了代码的灵活性和可维护性。 

上述代码运行时间太长了

提供几种更快的运行代码

代码另解

#include<algorithm>
using namespace std;
int main()
{
    int n, a[100000];
    int i;
    scanf("%d",&n);
    for (i = 0; i < n; i++)
    {
        scanf("%d", &a[i]);
    }
    sort(a, a + n);
    for (i = 0; i < n; i++)
    {
        printf("%d ", a[i]);
    }

}
  1. 读取数组元素:scanf("%d",&n); 读取用户输入的数组长度n。接下来的循环for (i = 0; i < n; i++) 读取用户输入的每个整数,并存储到数组a中。scanf("%d", &a[i]); 实现了这一操作。

  2. 排序数组:sort(a, a + n); 使用了STL中的sort函数对数组a进行排序。aa + n作为参数,分别表示待排序数组的起始地址和结束地址(不含结束地址),这会按照升序排列数组中的元素。

  3. 输出排序后的数组:通过循环for (i = 0; i < n; i++) 遍历排序后的数组,并使用printf("%d ", a[i]); 输出每个元素。注意,每个数字后面都有一个空格,以区分不同的元素 。

标签:sort,递归,int,quick,数组,AcWing785,排序,快速
From: https://blog.csdn.net/u014114223/article/details/139494625

相关文章

  • Hive3.1.2分区与排序(内置函数)
    1、Hive分区(十分重要!!)分区的目的:避免全表扫描,加快查询速度!在大数据中,最常见的一种思想就是分治,我们可以把大的文件切割划分成一个个的小的文件,这样每次操作一个个小的文件就会很容易了,同样的道理,在hive当中也是支持这种思想的,就是我们可以把大的数据,按照每天或者每小时切分......
  • 常见的排序算法——快速排序(二)
    本文记述了对快速排序的2项改进的基本思想和一份参考实现代码,并在说明了算法的性能后用随机数据进行了验证。◆思想本文实现了《算法(第4版)》书中提到的2项改进,切换到插入排序:对小规模子数组使用插入排序。减少在小规模数组中的递归调用能改进整个算法。三取样切分:将取样......
  • 【compshare】(3):使用UCloud(优刻得)的compshare算力平台,新增加SD-webui和大模型镜像,可
    关于UCloud(优刻得)旗下的compshare算力共享平台https://www.ucloud.cn/UCloud(优刻得)是中国知名的中立云计算服务商,科创板上市(股票代码:688158),中国云计算第一股,专注于提供可靠的企业级云服务,包括云服务器、云主机、云数据库、混合云、CDN、人工智能等服务。compshare......
  • 前端-Vue 快速上手
    Vue概念:Vue是一个用于构建用户界面的渐进式框架①构建用户界面:基于数据动态渲染页面②渐进式:循环渐进的学习③框架:一套完整的项目解决方案,提升开发效率↑(理解记忆规则)   规则→官网(v2.cn.vuejs.org / cn.vuejs.org)Vue的两种使用方式:1.Vue核......
  • 快速C++中的入门智能指针
    ✨前言✨......
  • C语言排序
    一、排序的运用生活中排序随处可见,比如我们高考时的排名,大学学校水平的排名等,打开京东,可以发现每样商品按照不同的方式排序,比如综合,销量,价格。其内部需要排序代码来完成。二、常见的排序算法一、交换排序一、冒泡排序冒泡排序是一种最容易想到的排序,但是其效率不高,没有实......
  • 快速一键化部署后端服务到k8s
    首先具备1、创建DockerfileFROMopenjdk:17RUNecho"Asia/Shanghai">/etc/timezoneWORKDIR/appCOPY*.jar/app/COPYpod_start.sh/app/RUNchmod+x/app/pod_start.shENTRYPOINT["/app/pod_start.sh"]2、pod_start.sh#!/bin/bashecho&......
  • 心诺安 x TapData:快速搭建云中数仓,助力电商企业实施“以用户为中心的”精细化运营
    使用TapData,化繁为简,摆脱手动搭建、维护数据管道的诸多烦扰,轻量代替OGG、DSG等同步工具,「CDC+流处理+数据集成」组合拳,加速仓内数据流转,帮助企业将真正具有业务价值的数据作用到实处,将“实时数仓”方法论落进现实。TapData持续迭代产品能力,优化用户体验的同时,也在不断探......
  • 头歌--交换类排序
    本关任务:编写函数通过比较数组相邻两个元素求数组最大值。#include<stdio.h>#include<stdlib.h>voidinput(int*&a,int&n);voidoutput(int*a,intn);voidcomp(int*a,intn);voidswap(int&a,int&b);intmain(){  inti,n;  int*a=NULL; ......
  • PrestoUDF故障排除与恢复:快速解决问题
    PrestoUDF故障排除与恢复:快速解决问题1.背景介绍Presto是一种开源的大数据分析引擎,由Facebook开发和维护。它旨在快速高效地查询来自不同数据源的大型分布式数据集。Presto支持使用SQL语言进行查询,并支持用户定义函数(UDF)的扩展功能。UDF(UserDefinedFunction)允许......