时间复杂度为O(nlogn)的两种排序算法

news2024/11/15 9:28:27

1.归并排序

归并排序的核心思想:如果要排序一个数组,我们先把数组从中间分成前后两部分,然后对前后两部分分别排序,再将排好序的两部分合并在一起,这样整个数组就都有序了。
归并排序使用的就是分治思想。分治,顾名思义,就是分而治之,将一个大问题分解成小的子问题来解决。小的子问题解决了,大的问题也就解决了。

在这里插入图片描述

public class MergeSort {
	public static void main(String[] args) {
		
		int[] arr = new int[] {7,4,2,8,9,5};
		
		mergeSort(arr,0,arr.length-1);
		
		System.out.println(Arrays.toString(arr));
	}
	
	/**
	 * 归并排序
	 * 原地排序:否 
	 * 稳定排序:是
	 * 空间复杂度:O(n)
	 * 时间复杂度:最好O(nlogn)——最坏O(nlogn)——平均O(nlogn)
	 * @param arr 要排序数组
	 * @param start 数组起始位
	 * @param last 数组结束位
	 * @return
	 */
	public static int[] mergeSort(int[] arr,int start,int last) {
		//也可以是(start+last)/2,这样写是为了防止数组长度很大造成两个相加大于int范围,导致溢出
		int mid = (last-start)/2+start;
		if(start<last) {
			mergeSort(arr,start,mid);//左数组排序
			mergeSort(arr,mid+1,last);//右数组排序
			merge(arr,start,mid,last);//合并两数组
		}
		return arr;
	}

	//合并数组
	public static int[] merge(int arr[],int start,int mid,int last) {
		int i=start;//左边数组下标
		int j=mid+1;//右边数组下标
		int[] tempArr = new int[last-start+1];//定义临时数组
		int k=0;
		while(i<=mid && j<=last) {
			if(arr[i]<arr[j]) {
				tempArr[k++] = arr[i++];
			}else {
				tempArr[k++] = arr[j++];
			}
		}
		
		while(i<=mid) {//将左边剩余元素移入到临时数组中
			tempArr[k++]=arr[i++];
		}
		
		while(j<=last) {//将右边剩余元素移入到临时数组中
			tempArr[k++]=arr[j++];
		}
		
		//把临时数组中的数据合并到新数组中
		for(int z=0;z<tempArr.length;z++) {
			arr[start+z] = tempArr[z];
		}
		
		return arr;
	}
}

2.快速排序

假设被排序的无序区间为[A[i],…,A[j]]

一、基准元素选取:选择其中的一个记录的关键字 v 作为基准元素(控制关键字);
二、划分:通过基准元素 v 把无序区间 A[I]…A[j] 划分为左右两部分,使得左边的各记录的关键字都小于 v;右边的各记录的关键字都大于等于 v;(如何划分?)
三、递归求解:重复上面的一、二步骤,分别对左边和右边两部分递归进行快速排序。
四、组合:左、右两部分均有序,那么整个序列都有序。上面的第 三、四步不用多说,主要是第一步怎么选取关键字,从而实现第二步的划分?

划分的过程涉及到三个关键字:“基准元素”、“左游标”、“右游标”

基准元素:它是将数组划分为两个子数组的过程中,用于界定大小的值,以它为判断标准,将小于它的数组元素“划分”到一个“小数值的数组”中,而将大于它的数组元素“划分”到一个“大数值的数组”中,这样,我们就将数组分割为两个子数组,而其中一个子数组的元素恒小于另一个子数组里的元素。

左游标:它一开始指向待分割数组最左侧的数组元素,在排序的过程中,它将向右移动。找大于基准值的数。

右游标:它一开始指向待分割数组最右侧的数组元素,在排序的过程中,它将向左移动。找小于基准值的数。

**注意:**上面描述的基准元素/右游标/左游标都是针对单趟排序过程的, 也就是说,在整体排序过程的多趟排序中,各趟排序取得的基准元素/右游标/左游标一般都是不同的。对于基准元素的选取,原则上是任意的。但是一般我们选取数组中第一个元素为基准元素(假设数组是随机分布的)

在这里插入图片描述

/**
 * 快速排序
 * 原地排序:是
 * 稳定排序:否
 * 空间复杂度:O(1)
 * 时间复杂度:最好O(nlogn)——最坏O(n^2)——平均O(nlogn)
 */
public class QuickSort {
	public static void main(String[] args) {
		int[] arr = new int[] {6,1,2,7,9,3,4,5,10,8};
		reQuickSort(arr,0,arr.length-1);
		System.out.println(Arrays.toString(arr));
	}
	
	public static void swap(int[] arr,int i,int j) {
		int temp = arr[i];
		arr[i] = arr[j];
		arr[j] = temp;
	}
	
	public static void reQuickSort(int[] arr,int left,int right) {
		if(right<=left) {
			return;//终止递归
		}else {
			int partition = partitionIt(arr,left,right);
			reQuickSort(arr,left,partition-1);//基准元素左边元素进行排序
			reQuickSort(arr,partition+1,right);//基准元素右边元素进行排序
		}
	}
	
	public static int partitionIt(int[] arr,int left,int right) {
		//为什么 j加一个1,而i没有加1,是因为下面的循环判断是从‐‐j和++i开始的.
		//而基准元素选的array[left],即第一个元素,所以左游标从第二个元素开始比较
		int i=left;
		int j=right+1;
		int pivot = arr[left];// pivot 为选取的基准元素(头元素)
		while(true) {
			while(j>left&&arr[--j]>pivot) {}
			
			while(i<right&&arr[++i]<pivot) {}
			
			if(i>=j) {
				break;//左右游标相遇时候停止, 所以跳出外部while循环
			}else {
				swap(arr,i,j);//左右游标未相遇时停止, 交换各自所指元素,循环继续
			}
		}
		swap(arr,left,j);//基准元素和游标相遇时所指元素交换,为最后一次交换
		
		return j;//一趟排序完成, 返回基准元素位置(注意这里基准元素已经交换位置了)
	}
}

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

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

相关文章

基于小程序+spring boot流浪动物救助系统-计算机毕设 附源码12783

小程序spring boot流浪动物救助系统 摘 要 随着我国经济迅速发展&#xff0c;人们对手机的需求越来越大&#xff0c;各种手机软件也都在被广泛应用&#xff0c;但是对于手机进行数据信息管理&#xff0c;对于手机的各种软件也是备受用户的喜爱&#xff0c;流浪动物救助系统被用…

Zabbix-agent批量部署脚本Linux and Windows(部署300+可用)

之前一直使用的是VC自动发现监控虚拟机&#xff0c;后来发现VC自动发现的虚拟机监控在OS内部性能方面存在数据差异&#xff0c;举例vmware.vm.memory.usage这个参数获取的数值和实际系统内部使用的完全不一致&#xff0c;还要会出现数据混乱的情况&#xff0c;就不一一叙述了&a…

2023年接口测试面试题大全,接口测试面试秘籍...

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 HTTP接口传递数据…

Vue.js2+Cesium 四、模型对比

Vue.js2Cesium 四、模型对比 Cesium 版本 1.103.0&#xff0c;低版本 Cesium 不支持 Compare 对比功能。 Demo 同一区域的两套模型&#xff0c;实现对比功能 <template><div style"width: 100%; height: 100%;"><divid"cesium-container"…

Istio 安全 授权管理AuthorizationPolicy

这个和cka考试里面的网络策略是类似的。它是可以实现更加细颗粒度限制的。 本质其实就是设置谁可以访问&#xff0c;谁不可以访问。默认命名空间是没有AuthorizationPolicy---允许所有的客户端访问。 这里是没有指定应用到谁上面去&#xff0c;有没有指定使用哪些客户端&#…

Socket 前端项目结构搭建

npm install socket.io-client --savenpm install element-plus --savenpm install vue-router4.0.12 --save简单的页面搭建 聊天系统登录前端实现 登录模板 <template><div class"login-container"><el-form ref"form" :model"fo…

现在的00后软件测试工程师,实在是太卷了

现在的小年轻真的卷得过分了。前段时间我们公司来了个00年的&#xff0c;工作没两年&#xff0c;跳槽到我们公司起薪18K&#xff0c;都快接近我了。后来才知道人家是个卷王&#xff0c;从早干到晚就差搬张床到工位睡觉了。 最近和他聊了一次天&#xff0c;原来这位小老弟家里条…

QDial

QDial 提供了一个圆角范围控制&#xff08;类似速度计&#xff09;。值的范围是0-99整数。 // 该信号受tracking值影响&#xff0c;当trackingfalse时&#xff0c;在释放按钮才发出该信号。当trackingtrue时&#xff0c;当值发生变化就会发出该信号。默认值是true。 // 使用函…

yolov3-tiny原理解析及代码分析

前言 从去年十一月份开始学习yolo神经网络用于目标识别的硬件实现&#xff0c;到现在已经六个月了。一个硬件工程师&#xff0c;C/C基础都差劲的很&#xff0c;对照着darknet作者的源码和网上东拼西凑的原理讲解&#xff0c;一点一点地摸索。刚开始进度很慢&#xff0c;每天都…

力扣 63. 不同路径 II

题目来源&#xff1a;https://leetcode.cn/problems/unique-paths-ii/description/ C题解&#xff1a;动态规划五部曲。 确定dp数组&#xff08;dp table&#xff09;以及下标的含义。dp[i][j] &#xff1a;表示从(0, 0)出发&#xff0c;到(i, j) 有dp[i][j]条不同的路径。确定…

一种RF测试执行优化思路(附可执行程序)

目录 一、递归形成用例集树 二、处理树形结构点击事件&#xff1a; 三、最终形成的执行语句。 提供一种思路&#xff0c;解决以下问题&#xff1a; 1、通过RIDE执行测试用例的话&#xff0c;无法调换待执行测试集顺序。 2、无法将当前选择保存为自己的测试集。 鉴于此&#…

SpringBoot第28讲:SpringBoot集成MySQL - MyBatis-Plus方式

SpringBoot第28讲&#xff1a;SpringBoot集成MySQL - MyBatis-Plus方式 本文是SpringBoot第28讲&#xff0c;MyBatis-Plus&#xff08;简称 MP&#xff09;是一个 MyBatis的增强工具&#xff0c;在 MyBatis 的基础上只做增强不做改变&#xff0c;为简化开发、提高效率而生。MyB…

C# 使用堆栈实现队列

232 使用堆栈实现队列 请你仅使用两个栈实现先入先出队列。队列应当支持一般队列支持的所有操作&#xff08;、、、&#xff09;&#xff1a;pushpoppeekempty 实现 类&#xff1a;MyQueue void push(int x)将元素 x 推到队列的末尾 int pop()从队列的开头移除并返回元素 in…

【java】使用maven完成一个servlet项目

一、创建项目 创建一个maven项目 maven是一个管理java项目的工具&#xff0c;根据maven的pom.xml可以引入各种依赖&#xff0c;插件。 步骤 打开idea&#xff0c;点击新建项目 点击创建项目&#xff0c;项目创建就完成了 进入时会自动打开pom.xml文件。 pom是项目的配置文件…

首次尝试鸿蒙开发!

今天是我第一次尝试鸿蒙开发&#xff0c;是因为身边的学长有搞这个的&#xff0c;而我也觉得我也该拓宽一下技术栈&#xff01; 首先配置环境&#xff0c;唉~真的是非常心累&#xff0c;下载一个DevEco Studio 3.0.0.993&#xff0c;然后配置环境变量这些操作不用多说&#xff…

LAXCUS分布式操作系统引领科技潮流,进入百度首页

信息源自某家网络平台&#xff0c;以下原样摘抄贴出。 随着科技的飞速发展&#xff0c;分布式操作系统做为通用基础平台&#xff0c;为大数据、高性能计算、人工智能提供了强大的数据和算力支持&#xff0c;已经成为了当今计算机领域的研究热点。近日&#xff0c;一款名为LAXCU…

ATFX汇市月报:7月美联储坚定加息,8月成利率决议空档期

7月汇市行情回顾—— 7月份&#xff0c;美元指数下跌1.01%&#xff0c;收盘在101.88点&#xff0c; 欧元升值0.76%&#xff0c;收盘价1.0997点&#xff1b; 日元升值1.41%&#xff0c;收盘价142.27点&#xff1b; 英镑升值1.08%&#xff0c;收盘价1.2835点&#xff1b; 瑞…

前端代码规范-2分钟教会你在nodejs中使用eslint定制团队代码规范

ESlint 是什么&#xff1f; ESlint官网 官网是这么写的&#xff1a; ESLint 是一个可配置的 JavaScript 检查器。 它可以帮助你发现并修复 JavaScript 代码中的问题。 问题可以是任何东西&#xff0c;从潜在的运行时错误&#xff0c;到不遵循最佳实践&#xff0c;再到风格问…

AWS——02篇(AWS之服务存储EFS在Amazon EC2上的挂载——针对EC2进行托管文件存储)

AWS——02篇&#xff08;AWS之服务存储EFS在Amazon EC2上的挂载——针对EC2进行托管文件存储&#xff09; 1. 前言2. 关于Amazon EFS2.1 Amazon EFS全称2.2 什么是Amazon EFS2.3 优点和功能2.4 参考官网 3. 创建文件系统3.1 创建 EC2 实例3.2 创建文件系统 4. 在Linux实例上挂载…

【CSS】视频文字特效

效果展示 index.html <!DOCTYPE html> <html><head><title> Document </title><link type"text/css" rel"styleSheet" href"index.css" /></head><body><div class"container"&g…