排序算法之快速排序算法介绍

目录

快速排序介绍

时间复杂度和稳定性

代码实现

C语言实现

c++实现

java实现


快速排序介绍

快速排序(Quick Sort)使用分治法策略。
它的基本思想是:选择一个基准数,通过一趟排序将要排序的数据分割成独立的两部分;其中一部分的所有数据都比另外一部分的所有数据都要小。然后,再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

快速排序流程:
(1) 从数列中挑出一个基准值。
(2) 将所有比基准值小的摆放在基准前面,所有比基准值大的摆在基准的后面(相同的数可以到任一边);在这个分区退出之后,该基准就处于数列的中间位置。
(3) 递归地把"基准值前面的子数列"和"基准值后面的子数列"进行排序。

下面以数列a={30,40,60,10,20,50}为例,演示它的快速排序过程(如下图)。

上图只是给出了第1趟快速排序的流程。在第1趟中,设置x=a[i],即x=30。
(01) 从"右 --> 左"查找小于x的数:找到满足条件的数a[j]=20,此时j=4;然后将a[j]赋值a[i],此时i=0;接着从左往右遍历。
(02) 从"左 --> 右"查找大于x的数:找到满足条件的数a[i]=40,此时i=1;然后将a[i]赋值a[j],此时j=4;接着从右往左遍历。
(03) 从"右 --> 左"查找小于x的数:找到满足条件的数a[j]=10,此时j=3;然后将a[j]赋值a[i],此时i=1;接着从左往右遍历。
(04) 从"左 --> 右"查找大于x的数:找到满足条件的数a[i]=60,此时i=2;然后将a[i]赋值a[j],此时j=3;接着从右往左遍历。
(05) 从"右 --> 左"查找小于x的数:没有找到满足条件的数。当i>=j时,停止查找;然后将x赋值给a[i]。此趟遍历结束!

按照同样的方法,对子数列进行递归遍历。最后得到有序数组!
————————————————

时间复杂度和稳定性

快速排序稳定性
快速排序是不稳定的算法,它不满足稳定算法的定义。
算法稳定性 -- 假设在数列中存在a[i]=a[j],若在排序之前,a[i]在a[j]前面;并且排序之后,a[i]仍然在a[j]前面。则这个排序算法是稳定的!

快速排序时间复杂度
快速排序的时间复杂度在最坏情况下是O(N2),平均的时间复杂度是O(N*lgN)。
这句话很好理解:假设被排序的数列中有N个数。遍历一次的时间复杂度是O(N),需要遍历多少次呢?至少lg(N+1)次,最多N次。
(01) 为什么最少是lg(N+1)次?快速排序是采用的分治法进行遍历的,我们将它看作一棵二叉树,它需要遍历的次数就是二叉树的深度,而根据完全二叉树的定义,它的深度至少是lg(N+1)。因此,快速排序的遍历次数最少是lg(N+1)次。
(02) 为什么最多是N次?这个应该非常简单,还是将快速排序看作一棵二叉树,它的深度最大是N。因此,快读排序的遍历次数最多是N次。

代码实现

C语言实现

/*** 快速排序:C 语言** @author skywang* @date 2014/03/11*/#include <stdio.h>// 数组长度
#define LENGTH(array) ( (sizeof(array)) / (sizeof(array[0])) )/** 快速排序** 参数说明:*     a -- 待排序的数组*     l -- 数组的左边界(例如,从起始位置开始排序,则l=0)*     r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)*/
void quick_sort(int a[], int l, int r)
{if (l < r){int i,j,x;i = l;j = r;x = a[i];while (i < j){while(i < j && a[j] > x)j--; // 从右向左找第一个小于x的数if(i < j)a[i++] = a[j];while(i < j && a[i] < x)i++; // 从左向右找第一个大于x的数if(i < j)a[j--] = a[i];}a[i] = x;quick_sort(a, l, i-1); /* 递归调用 */quick_sort(a, i+1, r); /* 递归调用 */}
}void main()
{int i;int a[] = {30,40,60,10,20,50};int ilen = LENGTH(a);printf("before sort:");for (i=0; i<ilen; i++)printf("%d ", a[i]);printf("\n");quick_sort(a, 0, ilen-1);printf("after  sort:");for (i=0; i<ilen; i++)printf("%d ", a[i]);printf("\n");
}

c++实现

/*** 快速排序:C++** @author skywang* @date 2014/03/11*/#include <iostream>
using namespace std;/** 快速排序** 参数说明:*     a -- 待排序的数组*     l -- 数组的左边界(例如,从起始位置开始排序,则l=0)*     r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)*/
void quickSort(int* a, int l, int r)
{if (l < r){int i,j,x;i = l;j = r;x = a[i];while (i < j){while(i < j && a[j] > x)j--; // 从右向左找第一个小于x的数if(i < j)a[i++] = a[j];while(i < j && a[i] < x)i++; // 从左向右找第一个大于x的数if(i < j)a[j--] = a[i];}a[i] = x;quickSort(a, l, i-1); /* 递归调用 */quickSort(a, i+1, r); /* 递归调用 */}
}int main()
{int i;int a[] = {30,40,60,10,20,50};int ilen = (sizeof(a)) / (sizeof(a[0]));cout << "before sort:";for (i=0; i<ilen; i++)cout << a[i] << " ";cout << endl;quickSort(a, 0, ilen-1);cout << "after  sort:";for (i=0; i<ilen; i++)cout << a[i] << " ";cout << endl;return 0;
}

java实现

/*** 快速排序:Java** @author skywang* @date 2014/03/11*/public class QuickSort {/** 快速排序** 参数说明:*     a -- 待排序的数组*     l -- 数组的左边界(例如,从起始位置开始排序,则l=0)*     r -- 数组的右边界(例如,排序截至到数组末尾,则r=a.length-1)*/public static void quickSort(int[] a, int l, int r) {if (l < r) {int i,j,x;i = l;j = r;x = a[i];while (i < j) {while(i < j && a[j] > x)j--; // 从右向左找第一个小于x的数if(i < j)a[i++] = a[j];while(i < j && a[i] < x)i++; // 从左向右找第一个大于x的数if(i < j)a[j--] = a[i];}a[i] = x;quickSort(a, l, i-1); /* 递归调用 */quickSort(a, i+1, r); /* 递归调用 */}}public static void main(String[] args) {int i;int a[] = {30,40,60,10,20,50};System.out.printf("before sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");quickSort(a, 0, a.length-1);System.out.printf("after  sort:");for (i=0; i<a.length; i++)System.out.printf("%d ", a[i]);System.out.printf("\n");}
}

上面3种语言的实现原理和输出结果都是一样的。下面是它们的输出结果:

before sort:30 40 60 10 20 50
after  sort:10 20 30 40 50 60

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

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

相关文章

C++Qt学习——添加资源文件

目录 1、创建好了文件之后&#xff0c;在左边空白处按下CtrlN&#xff0c;创建Qt 以及Qt Resource File 2、写入名称&#xff0c;点击下一步 3、可以发现已经创建好啦。 4、点击Add Prefix 5、写上前缀&#xff0c;最好加上斜杠 6、选择提前放好的图片或者icon 7、发…

Python异步编程探究:深入理解asyncio的使用和原理【第130篇—asyncio】

Python异步编程探究&#xff1a;深入理解asyncio的使用和原理 随着计算机应用程序的复杂性不断增加&#xff0c;对于高效处理I/O密集型任务的需求也越来越迫切。在Python中&#xff0c;asyncio模块提供了一种强大的异步编程方式&#xff0c;使得开发者能够轻松地处理并发任务&…

Vulnhub - DC-1

希望和各位大佬一起学习&#xff0c;如果文章内容有错请多多指正&#xff0c;谢谢&#xff01; 个人博客链接&#xff1a;CH4SER的个人BLOG – Welcome To Ch4sers Blog DC-1 靶机下载地址&#xff1a;DC: 1 ~ VulnHub 0x01 信息收集 Nmap扫描目标主机&#xff0c;发现开…

面试题 --- jdbc执行流程、MyBatis执行流程、MyBatis拦截器配置流程

jdbc执行流程 1. 注册驱动 2. 创建数据库操作对象 3. 执行sql语句 4 .处理操作结果 5 .关闭连接释放资源 MyBatis 执行流程 Executor执行器、MappedStatement 对象、 StatementHandler 语句处理器 关系可以用以下步骤概括 用户通过 SqlSession 调用一个方法&#xff0c;Sq…

双链表(上)

1.结构 1.带头双向循环链表 注意&#xff1a;这里的“带头”跟前面我们说的“头节点”是两个概念&#xff0c;实际前面的在单链表阶段称呼不严 谨&#xff0c;但是为了同学们更好的理解就直接称为单链表的头节点。 带头链表里的头节点&#xff0c;实际为“哨兵位”&#xff0c…

【ARM】MDK在programming algorithm界面添加FLM

【更多软件使用问题请点击亿道电子官方网站查询】 1、 文档目标 解决在programming algorithm界面中无法添加想要的Flash编程算法的问题 2、 问题场景 在对于Debug进行Flash Download进行配置的时候&#xff0c;在programming algorithm界面中有对应的Flash编程算法。可以通过…

数据结构 之 树

目录 1. 定义&#xff1a; 2. 概念&#xff08;重要&#xff09;&#xff1a; 3. 树的表示形式&#xff1a; 4. 树的应用&#xff1a; 1. 定义&#xff1a; 树是一种非线性的数据结构&#xff0c;&#xff0c;它是由n&#xff08;n>0&#xff09;个有限结点组成一个具有…

LeetCode——贪心算法(Java)

贪心算法 简介[简单] 455. 分发饼干[中等] 376. 摆动序列[中等] 53. 最大子数组和[中等] 122. 买卖股票的最佳时机 II[中等] 55. 跳跃游戏 简介 记录一下自己刷题的历程以及代码。写题过程中参考了 代码随想录的刷题路线。会附上一些个人的思路&#xff0c;如果有错误&#xf…

解决JVM进程被系统杀掉问题

背景 服务A在测试环境&#xff0c;隔几个小时接口就无法访问。登录机器查看&#xff0c;发现进程已经没了。大致猜想是进程使用的内存或CPU资源使用太多&#xff0c;导致被系统kill。 问题定位 使用dmesg命令查看进程被kill的详情。 > dmesg --time-format iso2024-03-0…

EasyCode 插件的具体使用

前言 EasyCode 是基于IntelliJ IDEA Ultimate版开发的一个代码生成插件&#xff0c;主要通过自定义模板&#xff08;基于velocity&#xff09;来生成各种你想要的代码。通常用于生成Entity、Dao、Service、Controller。如果你动手能力强还可以用于生成HTML、JS、PHP等代码。理…

iOS 判断触摸位置是否在图片的透明区域

装扮功能系列&#xff1a; Swift 使用UIScrollerView 实现装扮功能&#xff08;基础&#xff09;Swift 使用UIScrollerView 实现装扮功能&#xff08;拓展&#xff09;iOS 判断触摸位置是否在图片的透明区域 背景 在装扮功能中&#xff0c;一般都是长按使道具进入编辑状态&…

Docker拉取镜像存储不足

在使用Docker时&#xff0c;我们经常遇到一个问题&#xff0c;就是拉取镜像时提示存储空间不足。这是因为Docker在拉取镜像时需要将镜像文件下载到本地存储中&#xff0c;而有时本地存储空间不足以容纳完整的镜像文件。 本文将介绍一些解决这个问题的方法&#xff0c;并提供相…

Java学习笔记(11)

面向对象进阶 Static 静态变量 所有对象一起共享&#xff0c;就用static修饰 不属于对象&#xff0c;属于类的 可以用 类名.静态变量 “”&#xff1b;赋值 但是 对象.静态变量也可以访问到内容 Static内存图 Student这个类的字节码文件加载到方法区&#xff0c;并在内…

“人工智能+”成国策,天翼云如何打造大模型时代的驱动力样板?

文 | 智能相对论 作者 | 叶远风 两会政府工作报告中明确指出要制定支持数字经济高质量发展政策&#xff0c;开展“人工智能”行动&#xff0c;这意味着&#xff0c;“人工智能”已经成为国策。 在这种大背景下&#xff0c;大模型的重要性无疑被抬到了新的高度。 此时&#…

FPGA - 单总线协议(one-wire)

1&#xff0c;简介 单总线&#xff08;one-wire&#xff09;是美国 DALLAS 公司推出的外围串行扩展总线技术&#xff0c;与 SPI、I2C 等串行数据通信方式不同&#xff0c;它采用单根信号线&#xff0c;既传输时钟又传输数据&#xff0c;而且数据传输是双向的。它具有节省 I/O口…

【机器人控制 Robot Control】非线性控制(Non-linear Control)建模举例【新加坡南洋理工大学 NTU Singapore】

Non-linear Control Method Example: Non-linear Mechanical System Modelling of the System using Control Law Partitioning (Handwritten)

【Ubuntu-20.04】OpenCV-3.4.16的安装并对图片与视频处理

【Ubuntu-20.04】OpenCV-3.4.16的安装并对图片与视频处理 一、安装OpenCV-3.4.161.下载OpenCV-3.4.16安装包2.将安装包放到/home&#xff0c;并解压3.使用 cmake 安装 opencv4.配置环境5.查看 opencv 的版本信息 二、处理图片&#xff08;一&#xff09;创建文件夹 code &#…

Ansible管理主机的清单------------inventory

一、 Ansible组成 INVENTORY&#xff1a;Ansible管理主机的清单 /etc/ansible/hosts 需要管理的服务清单,(将你需要管理的主机 、地址 或者名字 写入此文件) MODULES&#xff1a;Ansible执行命令的功能模块&#xff0c;多数为内置核心模块&#xff0c;也可自定义 PLUGINS&…

观测云在 .NET 业务中分析性能问题的最佳实践

背景 某药业集团是一家以创新技术驱动的线下医疗数据 SaaS 平台建设和运营公司&#xff0c;其主营的某智慧医疗平台产品&#xff0c;围绕线下医疗场景痛点提供一体化服务解决方案。近期集团对其生物检材在线递检系统进行功能升级开发及 IaaS 平台迁移。在针对新系统和新基础设…

vue3/vue2若依框架对比,点击新增编辑跳转到新页面(新增编辑共用代码)

vue2若依框架&#xff1a; router里面定义好&#xff0c;编辑里面添加一个id {path: /filmManagement,component: Layout,hidden: true,redirect: noredirect,children: [{path: editFilmDetail,component: () > import(/views/filmManagement/editFilmDetail),name: editFi…