【算法】在?复习一下快速排序?

基本概念

快速排序是一种基于交换的排序算法,该算法利用了分治的思想。

整个算法分为若干轮次进行。在当前轮次中,对于选定的数组范围[left, right],首先选取一个标志元素pivot,将所有小于pivot的元素移至其左侧,大于pivot的则移动至其右侧,记录下最终pivot所处的位置pivot_pos。然后再利用递归,分别对左侧区间[left, pivot_pos - 1]和右侧区间[pivot_pos + 1, left]执行相同操作,依次类推,最终对整个数组完成排序。

请添加图片描述

以数组[16, 1, 2, 25, 9, 2, 5]为例,在递归实现中,其排序过程中交换策略如下图所示。当pivot_posi相等时,不需要交换,之所以先将pivot_pos++再交换的原因是,此时i指向的是小于pivot的元素,而pivot_pos是小于标志元素范围的右边界(如图),如果pivot_pos + 1 = i,则直接将这个右边界扩大1即可,而无需交换。如果不是,则将pivot_pos += 1以指向这个大于pivot的元素,并将其与小于pivotarray[i]进行交换,从而扩大右边界。下面给出了递归实现的示例代码。

int partition(int *array, int left, int right) {// * 默认选定首个元素为划分元素int pivot_pos = left, pivot_val = array[left];// * 遍历,将小于划分元素的值交换至其左侧for (int i = left + 1; i <= right; ++i) {if (array[i] < pivot_val) {pivot_pos += 1;if (pivot_pos != i) {swap(array[i], array[pivot_pos]);}}}array[left] = array[pivot_pos];array[pivot_pos] = pivot_val;return pivot_pos;
}// * 递归版快速排序 O(nlogn)
void quickSort(int *array, int left, int right) {if (left < right) {int pivotpos = partition(array, left, right);quickSort(array, left, pivotpos - 1);quickSort(array, pivotpos + 1, right);}
}

算法分析

时间复杂度:

  • 最好情况:每次划分均得到等长的两个子序列, O ( n l o g n ) O(nlogn) O(nlogn)
  • 最坏情况:每次划分得到的子序列只比上一层长度少1, O ( n 2 ) O(n^2) O(n2)
  • 平均情况: O ( n l o g n ) O(n log_n) O(nlogn)

此外,快速排序是一种不稳定的排序算法。

技巧应用

面试题 17.14. 最小K个数 - 力扣(LeetCode)

设计一个算法,找出数组中最小的k个数。以任意顺序返回这k个数均可。

示例:
输入: arr = [1,3,5,7,2,4,6,8], k = 4
输出: [1,2,3,4]
提示:
0 <= len(arr) <= 100000
0 <= k <= min(100000, len(arr))

请注意,上面这个题不要求返回的顺序。我们可以用快速排序对该数组进行排序操作。考虑一下快速排序的流程,是先对整体数组进行划分,然后再依次对划分元素的左侧和右侧进行划分,逐层递归。当划分元素的位置等于kk + 1时,[0, k - 1]实际上已经是数组前k小的数了,没有必要继续对数组做完全排序,因此可以将pivotpos == k || pivotpos == k + 1作为递归出口。

示例代码如下:

class Solution {
// 采用STL迭代器组合表示待排序的范围range
private:using Iter = vector<int>::iterator;Iter partition(Iter left, Iter right) {Iter pivot_pos = left;int pivot_val = *left;for (Iter i = left + 1; i < right; ++i) {if (*i < pivot_val) {pivot_pos += 1;if (pivot_pos != i) {iter_swap(pivot_pos, i);}}}iter_swap(left, pivot_pos);return pivot_pos;}void quicksort(Iter left, Iter right, Iter tar) {if (left < right) {Iter pivot_pos = partition(left, right);if (pivot_pos > tar + 1) {quicksort(left, pivot_pos, tar);}if (pivot_pos < tar) {quicksort(pivot_pos + 1, right, tar);}// 仅当等于tar或者tar+1时,// 才可判定pivot_pos的左侧范围为前k小或前k+1小}}public:vector<int> smallestK(vector<int>& arr, int k) {if (arr.empty() || k == 0) return {};quicksort(arr.begin(), arr.end(), arr.begin() + k - 1);vector<int> rtn(arr.begin(), arr.begin() + k);return rtn;}
};

拓展

在快速排序算法中,一个关键操作就是选择基准点(Pivot):元素将被此基准点分开成两部分。

最经常使用的就是选择一个区间的首元素或者尾元素,如本文所给出的示例。但是当数组部分有序时,这样做通常会使算法陷入坏情况,从 O ( n l o g n ) O(nlog_n) O(nlogn) 劣化到 O ( n 2 ) O(n^2) O(n2)

研究人员为此设计了一个快速排序的变体,选择首、尾、中间元素之中的中位数作为基准,依次避免特殊情况下算法劣化到 O ( n 2 ) O(n^2) O(n2)。但是即便性能有所提升,但是仍然有机会针对这种算法设计出一些特殊构造数组,以延长排序时间。这可能会造成服务器计算时间过程,进而为拒绝服务攻击提供可乘之机。

大卫·穆塞尔在1997年提出了内省排序算法introsort。旨在改善上述情况。introsort的主要步骤如下:

  1. 快速排序:最初使用快速排序对数组进行排序。
  2. 递归深度检查:在递归过程中,检查当前的递归深度。如果深度超过 2 l o g n 2 logn 2logn,则切换到堆排序。
  3. 堆排序:当递归深度过深时,使用堆排序对当前子数组进行排序。
  4. 插入排序:在数组小于一定阈值(通常是16或更小)时,使用插入排序进行排序,以提高小数组排序的效率。

使用这种组合算法,可以在正常快速排序算法的平均和最坏情况下,将时间复杂度均保持为 n l o g n nlogn nlogn

C++ STL算法库中的sort函数,在早期版本(LWG713之前)未对最坏情况的时间复杂度做要求,那个时候的标准库使用普通qsort实现就符合要求。在此之后,标准对最坏情况的时间复杂度进行了修正,后面的标准库实现版本使用的就是introsort算法。

LWG-xxx : 由 ISO C++ 标准委员会的图书馆工作组(LWG)跟踪的某个特定问题编号。

在这里插入图片描述

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/diannao/21467.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

EPIC Fantasy Village - Low Poly 3D Art(梦幻村庄乡村小镇模型)

这个包提供了一个以幻想为主题的多边形风格游戏,适合TopDown、RPG、冒险、社交和RTS。它允许你创建自己的美丽幻想村庄和角色。 EPIC 幻想村庄包 EPIC幻想村庄包提供了一个以幻想为主题的多边形风格游戏,适用于TopDown、RPG、冒险、社交和RTS游戏。这个包允许你创建自己的美丽…

Idefics2-8B多模态大模型微调指南

我们生活在大模型 (LLM) 时代&#xff0c;几乎每周你都会听到一种新的语言模型问世。从谷歌的 Gemini 和 Gemma 模型到 Meta 最新的 Llama 3 和微软的微型 Phi-3 模型&#xff0c;这些行业巨头之间正在进行激烈的在线竞争&#xff0c;以争夺头把交椅。 在这一连串的活动中&…

Java 18新特性深度解析:提升开发效率与性能的革新工具

在Java的世界中&#xff0c;每一次更新都带来新的惊喜和挑战。Java 18作为长期支持版本&#xff0c;不仅延续了Java语言的稳定性和可靠性&#xff0c;还引入了一系列令人兴奋的新特性&#xff0c;旨在进一步提升开发者的生产力和应用程序的性能。本文将深入探讨Java 18中的关键…

AtCoder Regular Contest 179 (ABC题)视频讲解

A - Partition Problem Statement You are given integers N N N and K K K. The cumulative sums of an integer sequence X ( X 1 , X 2 , … , X N ) X(X_1,X_2,\dots ,X_N) X(X1​,X2​,…,XN​) of length N N N is defined as a sequence Y ( Y 0 , Y 1 , … , …

交互设计如何助力传统技艺在当代复兴?

背景介绍 榫卯是中国传统木工中一种独特的接合技术&#xff0c;它通过构件间的凸凹部分相互配合来实现两个或多个构件的紧密结合。这种结构方式不依赖于钉子或其他金属连接件&#xff0c;而是利用木材自身的特性&#xff0c;通过精巧的设计和工艺&#xff0c;实现构件间的稳定…

GEE数据集:美国植被干旱响应指数 (Vegetation Drought Response Index,VegDRI)数据集

植被干旱响应指数 (VegDRI) 简介 植被干旱响应指数&#xff08;VegDRI&#xff09;是一个每周一次的地理空间模型&#xff0c;用于描述干旱对美国本土植被造成的压力。VegDRI干旱监测工具是由美国地质调查局EROS中心、内布拉斯加大学国家干旱缓解中心&#xff08;NDMC&#…

计算机网络学习实践:配置主机通过DHCP获取IP并通过域名访问web服务器

计算机网络学习实践&#xff1a;配置主机通过DHCP获取IP并通过域名访问web服务器 点一点就能配置&#xff0c;不需要输入命令 1.实验准备 实验环境&#xff1a;思科的模拟器 实验设备&#xff1a; 3个服务器&#xff0c;1个二层交换机&#xff08;不是三层的&#xff09;&a…

一个弹出的虚假安全警告去除

虚假的安全警告 poratus.azurewebsites.net Pornographic spyware detected! Remove viruses with Avira Antivirus 通过 Microsoft Edge GPT-4 (OpenAI) 这个提示可能是一个虚假的安全警告&#xff0c;被称为“恐吓软件”&#xff08;scareware&#xff09;&#xff0c;旨在…

名下企业查询,清晰明了;在线操作,方便快捷

在现代社会&#xff0c;越来越多的人开始涉足创业和投资&#xff0c;拥有自己的企业成为一种时尚。然而&#xff0c;随之而来的是繁琐的企业注册流程和复杂的信息查询。为了解决这个问题&#xff0c;挖数据平台推出了一项名下企业查询接口&#xff0c;提供了一种方便快捷的方式…

计算机网络介绍

计算机网络介绍 概述网络概述相关硬件 链路层VLAN概念VLAN 特点VLAN 的划分帧格式端口类型原理 STP概念特点原理 Smart Link概念特点组网 网络层ARP概念原理 IP概念版本IP 地址 IPv4IP 地址数据报格式 IPv6特点IP 地址数据报格式 ICMP概念分类报文格式 VRRP概念原理报文格式 OS…

片上电控系统集成技术

一、背景 片上电机控制系统集成技术&#xff08;On-Chip Motor Control System Integration&#xff09;是一种先进的电子工程技术&#xff0c;它主要聚焦于将复杂的电机控制算法和硬件组件整合到单一集成电路&#xff08;IC&#xff09;中&#xff0c;以便于高效、精确地管理…

计算机毕业设计 | 基于Koa+vue的高校宿舍管理系统宿舍可视化系统

项目介绍 项目背景 随着科技的发展&#xff0c;智能化管理越来越重要。大学生在宿舍的时间超过了1/3&#xff0c;因此良好的宿舍管理对学生的生活和学习极为关键。学生宿舍管理系统能够合理安排新生分配宿舍&#xff0c;不浪费公共资源&#xff0c;减轻学校管理压力&#xff…

关于工作组

什么是局域网&#xff08;内网&#xff09; 我们常说的内网指的就是局域网&#xff0c;局域网&#xff08;Local Area Network&#xff0c;简称LAN&#xff09;是指在相对较小的地理范围内&#xff0c;如一个办公室、学校、住宅区或建筑群内部&#xff0c;通过通信设备&#xf…

上位机图像处理和嵌入式模块部署(f407 mcu中tf卡读写和fatfs挂载)

【 声明&#xff1a;版权所有&#xff0c;欢迎转载&#xff0c;请勿用于商业用途。 联系信箱&#xff1a;feixiaoxing 163.com】 很早之前&#xff0c;个人对tf卡并不是很重视&#xff0c;觉得它就是一个存储工具而已。后来在移植v3s芯片的时候&#xff0c;才发现很多的soc其实…

如何监控慢 SQL?

引言&#xff1a;在开发和维护数据库驱动的应用程序时&#xff0c;监控慢 SQL 查询是确保系统性能和稳定性的关键一环。慢 SQL 查询可能会导致系统性能下降、资源浪费和用户体验差等问题。因此&#xff0c;及时监控和优化慢 SQL 查询对于保障系统的正常运行和用户满意度至关重要…

k8s 1.28.x 配置nfs

1.安装nfs&#xff0c;在每个节点上安装 yum install -y nfs-utils 2.创建共享目录(主节点上操作) mkdir -p /opt/nfs/k8s 3.编写NFS的共享配置 /opt/nfs/k8s *(rw,no_root_squash) #*代表对所有IP都开放此目录&#xff0c;rw是读写 4.启动nfs systemctl enable nfs-ser…

动态代理(黑马笔记)

一、BigStar 大明星类 package com.itheima.mydynamicproxy1; public class BigStar implements Star {//实现接口要重写里边的抽象方法private String name;public BigStar() {}public BigStar(String name) {this.name name;}//唱歌Override //表示重写接口中的方法public…

Java | Leetcode Java题解之第127题单词接龙

题目&#xff1a; 题解&#xff1a; class Solution {Map<String, Integer> wordId new HashMap<String, Integer>();List<List<Integer>> edge new ArrayList<List<Integer>>();int nodeNum 0;public int ladderLength(String beginW…

算法-找出N个数组的共同元素

一、代码与执行结果 财经新闻是大众了解金融事件的重要渠道&#xff0c;现有N位编辑&#xff0c;分别对K篇新闻进行专业的编辑与排版。需要您找出被这N位编辑共同编辑过的新闻&#xff0c;并根据这些新闻ID升序排列返回一个数组。 import random# 查找编辑共同处理的新闻id def…

RunLoop小白入门

核心概念 什么是 RunLoop ? RunLoop 是 iOS 和 macOS 应用程序框架中的一个核心概念&#xff0c;用于管理线程的事件处理。它可以看作是一个循环&#xff0c;用于持续接收和处理各种事件&#xff0c;如用户输入、定时器、网络事件等。RunLoop 在保持应用程序响应用户交互和系…