【快速排序】

news2025/1/10 11:00:12

快速排序

递归法

1、快排

  快速排序算法使基于分治策略的一个排序算法,其基本思想是,对于输入的子数组 nums[left : right] 按以下3个步骤排序:

(1)分解:以 nums[left] 为基准元素将 nums[left : right] 划分成3段 nums[left: mid-1],nums[mid] 和 nums[mid+1:right],使得nums[left:mid-1] 中任何元素小于等于 nums[mid], nums[mid+1:right] 中任何元素大于等于 nums[right]。下标 mid 在划分过程中确定。

(2)递归求解: 通过递归调用快速排序算法,分别对 nums[left:mid-1] 和 nums[mid+1:right] 进行排序。

(3)合并 : 由于对 nums[left:mid-1] 和 nums[mid+1:right] 的排序是就地进行的,所以在 nums[leftmid-1] 和 nums[mid+1:right] 都已排好的序后不需要执行任何计算,nums[left:right] 就已排好序。

//递归法,双向开工,left向左 right向右
//打印函数
void PrintInt(const int* nums, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%5d", nums[i]);
	}
	printf("\n");
}

//划分函数的功能是将小于tmp的元素放在左半部分,大于tmp放在右边部分
int Partition(int* nums,int left, int right)//划分函数,i==j 时while循环推出,此时i or j左边均小于nums[i],youbianjun
{
	int i = left, j = right;
	int tmp = nums[i];
	while (i < j)// i < j是为了不发生划分时交叉了
	{
		while (i < j && nums[j] > tmp)
			--j;
		if (i < j)
			nums[i] = nums[j];
		while (i < j && nums[i] <= tmp)
			++i;
		if (i < j)
			nums[j] = nums[i];
	}
	nums[i] = tmp;
	return i;//return j;
}
//快排
void QuickSort(int *nums, int left, int right)
{
	if (left < right)
	{
		int mid = Partition( nums, left,  right);
		QuickSort(nums, left,mid - 1);
		QuickSort(nums, mid + 1, right);
	}
}
主函数
int main()
{
	int ar[] = { 56,23,78,45,90,89,12,34,56,67,89,100 };
	int n = sizeof(ar) / sizeof(ar[0]);
	PrintInt(ar, n);
	QuickSort(ar, 0, n - 1);
	PrintInt(ar, n);
}

2、快排的优化

快 排 的 退 化 , 当 数 据 有 序 时 , 快 排 的 速 度 越 慢 , 快排的退化,当数据有序时,快排的速度越慢, 退
分析:
  快排的的运行时间于划分是否对称性有关,最坏的情况是划分中两个区域分别包含n-1个元素和1个元素的情况,Partition的计算时间为O(n),若每一步都出现这种不对称划分,计算时间为O(n^2).

解决方法:   利用随机选择策略使初始数组变的无序
  修改Partition算法,在数组还没有被划分时,可以在nums[left : right]中随机选择一个元素作为划分基准,这样可以使划分基准的选择是随机的,划分比较对称。

//随机策略,使数据更有序
int RandPartition(int* nums, int left, int left)
{
	srand(time(nullptr));
	int ropos = (rand() % (right - left + 1)) + left;//随机位置,加left是因为right - left是相对法,要加上此时的left
	std::swap(nums[left], nums[ropos]);//交换随机位置和left的值
	return Partition(nums, left, right);//调用划分函数
}
//递归法,双向开工,left向左 right向右
//打印函数
void PrintInt(const int* nums, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%5d", nums[i]);
	}
	printf("\n");
}

//划分函数的功能是将小于tmp的元素放在左半部分,大于tmp放在右边部分
int Partition(int* nums,int left, int right)//划分函数,i==j 时while循环推出,此时i or j左边均小于nums[i],youbianjun
{
	int i = left, j = right;
	int tmp = nums[i];
	while (i < j)// i < j是为了不发生划分时交叉了
	{
		while (i < j && nums[j] > tmp)
			--j;
		if (i < j)
			nums[i] = nums[j];
		while (i < j && nums[i] <= tmp)
			++i;
		if (i < j)
			nums[j] = nums[i];
	}
	nums[i] = tmp;
	return i;//return j;
}
//快排
void QuickSort(int *nums, int left, int right)
{
	if (left < right)
	{
		int mid = Partition( nums, left,  right);
		QuickSort(nums, left,mid - 1);
		QuickSort(nums, mid + 1, right);
	}
}
主函数
int main()
{
	int ar[] = { 56,23,78,45,90,89,12,34,56,67,89,100 };
	int n = sizeof(ar) / sizeof(ar[0]);
	PrintInt(ar, n);
	QuickSort(ar, 0, n - 1);
	PrintInt(ar, n);
}

3、非递归法

利用队列或栈来实现非递归快排

#include<iostream>
#include<stdio.h>
#include<queue>
//非递归
void PrintInt(const int* nums, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%5d", nums[i]);
	}
	printf("\n");
}
int Partition(int* nums, int left, int right)//划分函数,i==j 时while循环推出,此时i or j左边均小于nums[i],youbianjun
{
	int i = left, j = right;
	int tmp = nums[i];
	while (i < j)// i < j是为了不发生划分时交叉了
	{
		while (i < j && nums[j] > tmp)
			--j;
		if (i < j)
			nums[i] = nums[j];
		while (i < j && nums[i] <= tmp)
			++i;
		if (i < j)
			nums[j] = nums[i];
	}
	nums[i] = tmp;
	return i;//return j;
}

void QuickSort(int *nums, int left, int right)
{
	std::queue<int> qu;
	qu.push(left);
	qu.push(right);
	while (!qu.empty())//为空跳出
	{
		int sleft = qu.front();//取队头
		qu.pop();//出队
		int sright = qu.front();
		qu.pop();
		int mid = Partition(nums, sleft, sright);
		if (sleft < mid - 1)
		{
			qu.push(sleft);
			qu.push(mid - 1);
		}
		if (mid + 1 < sright)
		{
			qu.push(mid + 1);
			qu.push(sright);
		}
	}
	
}

int main()
{
	int ar[] = { 56,23,78,45,90,89,12,34,56,67,89,100 };
	int n = sizeof(ar) / sizeof(ar[0]);
	PrintInt(ar, n);
	QuickSort(ar, 0, n - 1);
	PrintInt(ar, n);
}

结 果 : 结果:
在这里插入图片描述

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

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

相关文章

Wisej.NET 3.2 WiseJ Framework Crack

Web Development for Business Applications build ›› migrate ›› modernize ›› See the amazing things people are doing with Wisej.NET Customer storiesmadewithWisej.com Wisej 3.2 is released! read more ›› Wisej.NET Rapid .NET Web Development - 3.2 beta …

【深度学习】第一门课 神经网络和深度学习 Week 1 深度学习概论

文章目录 目录 目录 文章目录 1.1 欢迎来到深度学习 1. 为什么要学深度学习&#xff1f; 2. 我们将学习到哪些内容&#xff1f; 1.2 什么是神经网络&#xff1f; 引例 问题 题解 抽象 复杂化问题 建模 1.3 用神经网络进行监督学习 1. 概念辨析 2. 用神经网络进…

Hive 实战第一讲 hive基本介绍以及环境搭建

文章目录 1.Hive介绍1.1 hive 基本情况1.2 Hive架构原理1.3 Hive 安装1.4 元数据配置1.5 hive 服务部署1.6Hive常用交互命令1.6.1 Hive参数配置方式 1.Hive介绍 1.1 hive 基本情况 hive基于Hadoop的一个数据仓库工具&#xff0c;可以将结构化的数据文件映射为一张表。 Hive是…

程序员必备的工具网站,大幅度提升你的工作效率

前言&#xff1a; 相信很多人不光是在编程的过程中&#xff0c;在平时的生活中&#xff0c;也经常会收藏一些有用的网站&#xff0c;方便使用的时候&#xff0c;靠这些网站来解决一些麻烦的事情。 我就把我收藏的一些经常用的工具网站分享给你们&#xff0c;你们也可以收藏起来…

web网络安全

在学习网络安全之前&#xff0c;必须要先知道一个组织——OWASP。 OWASP是一个开源的、非盈利的全球性安全组织&#xff0c;致力于应用软件的安全研究。我们基于该组织公布的技术文档来学习相关网络攻击原理和预防措施&#xff0c;web安全的核心是——永远不要相信用户传过来的…

OLED显示实验

实验内容 点亮OLED&#xff0c;并实现ASCII 字符的显示。 OLED简介 OLED&#xff0c;即有机发光二极管&#xff08;Organic Light-Emitting Diode&#xff09;&#xff0c;又称为有机电激光显示&#xff08;Organic Electroluminesence Display&#xff0c; OELD&#xff09…

Java10

Java10 &#xff08;一&#xff09;、配置文件&#xff08;二&#xff09;、多线程2.1 并发和并行2.2 多线程的实现方式2.3 常见成员方法2.3.1 线程的优先级2.3.2 守护线程&#xff08;备胎线程&#xff09;2.3.3 礼让线程和插入线程 2.4 线程生命周期2.4 线程安全问题2.5 锁2.…

Android Input kl文件实现键值映射

Android Keyevent定义在KeyEvent.java 截图对应 public static final int KEYCODE_SYSRQ 120; adb shell input keyevent SYSRQLinux Scancode定义在input-event-codes.h #define KEY_SCALE 120可以看到是不对应的 本来想通过指纹双击实现截图功能&#xff0c;发现上报scanco…

浅谈性能测试策略的理解

面对日益复杂的业务场景和不同的系统架构&#xff0c;前期的需求分析和准备工作&#xff0c;需要耗费很多的时间。而不同的测试策略&#xff0c;也对我们的测试结果是否符合预期目标至关重要。 这篇博客&#xff0c;聊聊我个人对常见的性能测试策略的理解&#xff0c;以及它们…

tkinter+爬虫(re库,tkinter库详解)

1.安装和认识本次实验所需要的库 re库&#xff08;正则库&#xff0c;本次实验用于匹配文本&#xff09; tkinter库 &#xff08;GUI库&#xff0c;用于制作可视化界面&#xff09; requests库 &#xff08;网络请求库&#xff0c;用于制作爬虫&#xff09; re和tkinter均为…

node 脚本调试

Node 脚本调试 node --inspect-brk index.js 执行以上命令&#xff0c;然后打开浏览器的控制台会发现有个node的logo 点击这个图标就可以开始调试代码 调试webpack 只需要找到webpack的执行入口&#xff0c;然后执行以下命令&#xff0c;只要是node脚本都可以进行调试。 n…

Shell脚本完成web服务器的建设

一&#xff0c;要求 1&#xff0c;安装httpd软件 2&#xff0c;定义防火墙规则 3&#xff0c;设置selinux为强制模式 4&#xff0c;web服务器的端口为8080 5&#xff0c;web服务器的内容目录为 /www/8080 6&#xff0c;所有操作开机有效 7&#xff0c;所有操作必须进行…

2022年上半年软件设计师下午试题

【试题四】&#xff08;共15分&#xff09; 阅读下列说明和C代码&#xff0c;回答问题1至问题3&#xff0c;将解答写在答题纸的对应栏内。 工程计算中经常要完成多个矩阵相乘的计算任务&#xff0c;对矩阵相乘进行以下说明。 (1)两个矩阵相乘要求第一个矩阵的列数等于第二个…

适合广告行业使用的企业网盘工具

Zoho Workdrive 是一款非常适合广告行业使用的企业网盘工具&#xff0c;它可以帮助广告行业进行高效、有序的项目管理。作为一名广告行业从业者&#xff0c;你是否遇到过以下问题&#xff1f; 2.文件无法有效共享 团队合作效率低下客户需求无法及时满足 这些问题都会严重影响项…

【Linux】Redis高可用概述2(Redis 发布订阅、Redis 事务、Redis主从复制)

一、Redis 发布订阅 Redis 发布订阅(pub/sub)是一种消息通信模式&#xff1a;发送者(pub)发送消息&#xff0c;订阅者(sub)接收消息。 发送者可以向多个订阅者发送消息&#xff0c;订阅者可以收到多个发送者送来的消息&#xff0c;也就是是说发送者和订阅者是多对多的关系 实例…

MATLAB中资源管理器无法安装资源解决方法详细教程

摘要&#xff1a;介绍使用MATLAB获取附加功能时出现“续订软件维护服务”的界面问题解决方案&#xff0c;即使用预先从官网下载的安装包文件&#xff0c;直接运行离线安装文件后会自动弹出附加功能管理界面&#xff0c;这时可以安装该附加工具&#xff0c;详细过程见以下介绍。…

ProtoBuf原理

一、文章 https://zhuanlan.zhihu.com/p/404782892 二、测试 1.test.proto syntax "proto3";package proto; option go_package "./;proto";message Msg{uint32 age1 1;sint32 age2 2;string name 3;bytes data 4; }2.main.go package mainimpor…

【滤波】多元卡尔曼滤波器

本文主要翻译自rlabbe/Kalman-and-Bayesian-Filters-in-Python的第6章节06-Multivariate-Kalman-Filters&#xff08;多元卡尔曼滤波器&#xff09;。 %matplotlib inline#format the book import book_format book_format.set_style()简介 我们现在准备研究和实现完整的、多…

财报解读:Q2业绩指引未达预期,狂奔的爱彼迎要减速了?

全球民宿龙头爱彼迎Airbnb迎来了一个强劲的开端。 美东时间5月9日盘后&#xff0c;爱彼迎发布了2023年第一季度财报。财报显示&#xff0c;爱彼迎一季度营收、净利润、总预订金额都获得了不同程度增长&#xff0c;超出市场预期。美中不足的是&#xff0c;公司预计二季度营收下…

分组卷积和深度可分离卷积

文章目录 一、常规卷积操作二、分组卷积三、深度可分离卷积 一、常规卷积操作 在图中&#xff0c;输入的特征图大小为 H * W * 4 卷积核个数为 2 个&#xff0c;每个卷积核的大小为 K * K * 4 输出的特征图大小为 H’ * W’ * 2 二、分组卷积 &#xff01;&#xff01;&#…