package demo;
import java.util.Arrays;
public class SortUtil {
private static void printArr(int[] arr) {
System.out.println(Arrays.toString(arr));
}
private static void checkSort(int[] arr) {
for (int i = 0; i < arr.length - 1; i++) {
if (arr[i] > arr[i + 1]) {
throw new RuntimeException("Sort Error!");
}
}
}
private static void swap(int[] arr, int i, int j) {
int temp = arr[i];
arr[i] = arr[j];
arr[j] = temp;
}
// 本机测试
public static void main(String[] args) {
// int[] arr = {4, 3, 5};
int[] arr = new int[50000 * 100];
java.util.Random random = new java.util.Random();
for (int i = 0; i < arr.length; i++) {
arr[i] = random.nextInt(arr.length);
}
// System.out.println("排序前:");
// printArr(arr);
long s = System.currentTimeMillis();
// bubbleSort(arr);// 50000 数据 5000+ ms
// selectSort(arr);// 50000 数据 1700+ ms
// insertSort(arr);// 50000 数据 360+ ms
quickSort(arr, 0, arr.length - 1);// 50000 * 100 数据 770 ms
// mergeSort(arr);// 50000 * 100 数据 1300 ms
// mergeSort(arr, 0, arr.length - 1);// 50000 * 100 数据 1300 ms
// heapSort(arr);// 50000 * 100 数据 1650 ms
long e = System.currentTimeMillis();
System.out.println("耗时:" + (e - s));
checkSort(arr);
System.out.println("排序正确!");
// System.out.println("排序后:");
// printArr(arr);
}
private static void bubbleSort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放
for (int j = len - 1; j > i; j--) { // 从后往前,把最小(大)的挪动到目标位置
if (arr[j] < arr[j - 1]) { // 后面的大于前面
swap(arr, j, j - 1);//如果没有发送交互则表示排序已经完成,但会多n次判断
}
}
}
}
private static void selectSort(int[] arr) {
int len = arr.length;
for (int i = 0; i < len - 1; i++) { //要放置正确元素的目标位置,最后一个不用放
int min = i;
for (int j = i + 1; j < len; j++) {
if (arr[j] < arr[min]) { // 后面的大于前面
min = j;
}
}
swap(arr, i, min);
}
}
private static void insertSort(int[] arr) {
for (int i = 1; i < arr.length; i++) {// 第一个不需要插入排序
int temp = arr[i];
int j = i - 1;
while (j >= 0 && temp < arr[j]) {
arr[j + 1] = arr[j];
j--;
}
arr[j + 1] = temp;
}
}
/*** quick ***/
private static void quickSort(int[] arr, int left, int right) {
if (left >= right) return;
int pivotIndex = partition(arr, left, right);
quickSort(arr, left, pivotIndex - 1);//排序 target 前面的
quickSort(arr, pivotIndex + 1, right);//排序 target 后面的
}
private static int partition(int[] arr, int left, int right) {
int pivot = arr[right];//堆排序是原地排序,这个额外空间可以省去的,这里为了语义明确在此声明
int target = left;
for (int i = left; i < right; i++) {
if (arr[i] < pivot) {
swap(arr, target++, i);
}
}
swap(arr, target, right);// target 已经处在正确的位置
return target;
}
/*** merge:递归实现 从外向里 ***/
private static void mergeSort(int[] arr, int left, int right) {
if (left == right) return;//待排序列长度为1
int middle = (left + right) / 2;
mergeSort(arr, left, middle);
mergeSort(arr, middle + 1, right);
merge(arr, left, middle, right);
}
/*** merge:迭代实现 从里向外 ***/
private static void mergeSort(int[] arr) {
int len = arr.length;
int left;//需要归并的左坐标
int middle;//需要归并的中坐标(定义为左侧的结束端坐标),也就是步长的最后一个
int right;//需要归并的右坐标
for (int mergeLen = 1; mergeLen < len; mergeLen *= 2) {
left = 0;
while (left + mergeLen < len) { // 有后面的数组需要归并
middle = left + mergeLen - 1;
right = middle + mergeLen < len ? middle + mergeLen : len - 1;
merge(arr, left, middle, right);
left = right + 1;
}
}
}
private static void merge(int[] arr, int left, int leftEnd, int right) {
int len = right - left + 1;
int[] temp = new int[len];//辅助空间
int tempIndex = 0;//辅助空间指针
int i = left;//左侧指针
int j = leftEnd + 1;//右侧指针
while (i <= leftEnd && j <= right) {
if (arr[i] <= arr[j]) {// 带等号保证归并排序的稳定性
temp[tempIndex++] = arr[i++];
} else {
temp[tempIndex++] = arr[j++];
}
}
while (i <= leftEnd) {
temp[tempIndex++] = arr[i++];//左侧数组未
}
while (j <= right) {
temp[tempIndex++] = arr[j++];
}
for (int k = 0; k < len; k++) {
arr[left + k] = temp[k];//将辅助空间内容替换至真实数组的 left-right 空间
}
}
/*** heap ***/
private static void heapSort(int[] arr) {
buildHeap(arr);//初始化大顶堆
int maxHeapIndex = arr.length - 1;
while (maxHeapIndex > 0) {// 堆(无序区)元素个数大于1,未完成排序
swap(arr, 0, maxHeapIndex--);// 此处交换操作很有可能把后面元素的稳定性打乱,所以堆排序是不稳定的排序算法
adjustHeap(arr, 0, maxHeapIndex);// 从新的堆顶元素开始向下进行堆调整,时间复杂度O(logn)
}
}
private static void buildHeap(int[] arr) { // 建堆,时间复杂度O(n)
int len = arr.length;
for (int i = len / 2 - 1; i >= 0; i--) {//从最后一个非叶子节点开始,向上调堆,当i==0时,所有堆成为最大堆
adjustHeap(arr, i, len - 1);
}
}
private static void adjustHeap(int[] arr, int i, int maxIndex) {
int leftChild = i * 2 + 1;
int rightChild = i * 2 + 2;
int max = i;
if (leftChild <= maxIndex && (arr[leftChild] > arr[max])) {
max = leftChild;
}
if (rightChild <= maxIndex && (arr[rightChild] > arr[max])) {
max = rightChild;
}
if (max != i) {
swap(arr, i, max);//把最大的换到当前堆顶,然后继续调剂被破坏的子堆
adjustHeap(arr, max, maxIndex);// 保证被破坏的子堆继续维持大顶堆性质
}
}
}
相关推荐
告别Failed to start错误!保姆级教程:用Ubuntu20.04安装盘搞定GRUB与系统服务修复
本文提供Ubuntu20.04系统启动失败的专业修复指南,详细讲解如何利用安装盘解决GRUB与系统服务问题,避免重装系统导致的数据丢失。涵盖分区挂载、chroot环境操作、服务诊断与修复等实用技巧,帮助用户高效恢复系统正常运行。
java实现选择、插入、归并、快速排序以及优化
选择排序 一共n-1轮循环,第一轮将第一个数与它后面所有数比较,若它大于后面某个数则交换,然后继续拿这个新的索引为0的数与后面的数继续比较,直到这一轮循环结束。第二轮循环则拿索引为1的数与它后面的数继续比较(重复上一轮的操作)。 public static void selectsort(int[] arr){ for(int i=0;i<arr.length-1;i++){
MODIS 遥感数据批量下载(使用Cygwin)
MODIS 遥感数据批量下载(使用Cygwin)包含Cygwin的下载教程
九大排序算法总结(转)
原文链接https://blog.youkuaiyun.com/foreverling/article/details/43798223, 感谢原文作者 楚兴大牛的分享,转载只为了能方便阅读,如有侵权还请联系,我将马上对文章进行删除 转 九大排序算法总结 排序算法可以分为内部排序和外部排序,...
静态时序分析(STA)_深入解析Data to Data Checks的零周期挑战
本文深入解析了静态时序分析(STA)中Data to Data Checks的核心概念与零周期挑战。重点探讨了当Setup要求值超过时钟周期时,工具如何调整发射沿,并导致Hold检查的发射与捕获沿“分裂”这一反直觉现象。文章通过案例详细解读了时序报告,并提供了通过调整约束或接受多周期保持两种策略来应对这一挑战,帮助工程师正确理解和处理此类复杂时序检查。
openEuler 20.03 LTS面向RK3399移植系列(3)—openEuler 20.03 LTS面向Firefly RK3399的第一个版本(Linux kernel 4.4)
任务动机:完成openEuler面向RK3399开发板的移植。 任务描述:按照固件烧写准备,固件获取,固件打包和烧写的步骤实现openEuler面向RK3399开发板的移植,整理过程和相关命令记录到文档。 1. 制作openEuler的rootfs.img 1.1 开发环境 树莓派--openEuler系统 openEuler 20.03 LTS 的内测版本镜像,下载。 1.2 具体操作 1.2.1 ssh远程连接树莓派 确定树莓派IP ssh连接 1.2.2 制作rootfs.img
快速排序与归并排序Java实现版
快速排序 快速排序(Quicksort) 是一种排序算法,平均时间复杂度为:O(n log n),最坏需要 O(n²),但很少见,快速排序之所以叫快速排序,就是因为它比一般的排序算法要快。 快速排序使用了分而治之的思想,步骤如下: 选择基准值(pivot) 将数组分成两个子数组:小于基准值的元素和大于基准值的元素 对这两个子数组进行快速排序 不同的选取基数值策略对排序性能都有很大的影响。 递归...
深度可分离卷积(DepthwiseSeparableConvolution):Depthwise卷积与Pointwise卷积
深度可分离卷积不用多说,在轻量级网络架构方面是一个绕不开的话题,只要接触深度学习多多少少会接触。深度可分离卷积即DepthwiseSeparableConvolution,该卷积将一个常规卷积过程划分成两个完成Depthwise卷积和Pointwise卷积,在保证输出一样时,计算量大大降低。首先来看,一个常规卷积是怎么实现的。其示意图如果我们从通道数变换的角度来看,卷积就是将3通道的tensor变为了4通道的tensor,我们来看看深度可分离卷积是怎么实现通道的变化的。...
Java排序之快排、归并、及冒泡排序
1、快排 import java.util.Arrays; public class QuickRem { public static void main(String[] args) { int[] data = {9, -16, 21, 23, -30, -23, 22, 24, 22, 44, 45}; System.out.println("...
SpringBoot + MyBatis-Plus 高效实现数据变更记录:从注解到通用审计方案(附源码)
*** 数据变更审计插件* 拦截增删改操作,自动记录变更日志*/@Component@Resource/*** 拦截SQL执行*/@Override/*** 数据变更审计插件* 拦截增删改操作,自动记录变更日志/*** 拦截SQL执行。
基于YOLOv11的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理系统
基于YOLOv11的水果/商品/食堂/蔬菜/饮料/书籍识别与计价系统,前台+后台管理系统
七大排序算法(Java实现)——冒泡、快排、插入、希尔、选择、堆排、归并
*** 交换排序:稳定,O(n^2)* 1. 冒泡排序:* 相邻两个元素两两比较,若逆序则交换* 每一轮会确定一个最大值到它最后的位置上,只需n-1轮排序* 优化:如果某一轮排序从头至尾没有发生交换,说明已经有序,结束* @param array 待排序列*/i < n - 1;i++) { // n-1轮排序j++) { // 每轮会确定一个最值if(array[j] > array[j + 1]) { // 逆序则交换// 本轮发生了交换。
使用自制的NTC测量模块测试Plecs的热仿真效果
可以测试:您完全可以用这个模型来测试热仿真。NTC 模型是连接电气域和热域的关键桥梁。实现闭环:通过这种方式,您创建了一个高度真实的正反馈闭环系统:负载增加 -> 损耗增加 -> 温度升高 -> NTC 阻值变化 -> 控制电路可能因此调整(如降低频率或电流)-> 损耗变化 -> 温度变化。应用场景:这对于设计过温保护 (OTP) 电路风扇控制系统以及分析热失控条件非常有用。单位:确保热域中使用的单位( Kelvin 或 Celsius )与您的 C-Script 模型输入期望的单位一致。
Java 实现常见六大排序算法(快排、堆排、归并、选择、冒泡、插入)
package sort; import java.util.ArrayList; import java.util.List; import java.util.Scanner; public class Main{ //1.快排 + 两种优化 public static void quickSort(List<Integer> arr,int l,int r) { if(r-l <= 10){ //优化一:当数据量较小时改为插入排序
IDEA的使用指南
IDEA基于java的使用手册,可以最快速的上手,在使用中不断的丰富自己的使用技巧.
pscad IEEE标准系统搭建说明
pscad IEEE标准系统搭建说明,包含典型的IEEE 9节点、14节点、30节点、39节点和118节点系统。内含标准测试系统的原始数据和潮流结果。
七大常见排序
本文介绍了七种常见排序算法及其实现。主要内容包括:1) 插入排序(直接插入排序和希尔排序),希尔排序通过分组插入优化效率;2) 选择排序(直接选择排序和堆排序),堆排序利用堆结构提高效率;3) 交换排序(冒泡排序和快速排序),快速排序采用分治策略,提供hoare、挖坑法和双指针三种实现方式;4) 归并排序,通过分解和合并实现排序。每种算法都给出了C语言实现代码,并分析了时间复杂度和空间复杂度。其中快速排序和归并排序的时间复杂度最优,为O(nlogn)。文章通过图示和代码详细说明了各算法的实现原理和优化方法。
霍尼韦尔SoftMaster使用说明
霍尼韦尔SoftMaster使用说明
【Java】——基础算法Java代码
算法基础笔记,随学随更
锂电池充电器电路设计 里面有电路
锂电池充电器电路设计 里面有电路 3.7V升压到5V电路设计。
Java排序算法全解析:从冒泡到TimSort的工程实践
排序算法是数据结构与算法的基础,也是Java面试中高频考察点。理解时间复杂度、空间复杂度和稳定性等评价维度,能帮助你从本质上区分冒泡、选择、插入、归并、快排和堆排序的适用场景。快速排序凭借原地分区和缓存友好性成为工程首选,而归并排序以稳定性见长,堆排序则在Top K问题中发挥价值。JDK的Arrays.sort根据数据类型和数组长度动态选择双轴快排或TimSort,充分体现了算法设计中的工程取舍。本文结合实际代码与踩坑经验,梳理了常见排序算法的原理、实现细节及性能对比,助力开发者夯实内功并从容应对面试。
Java排序算法全解析:从冒泡到快排的工程实践与面试考点
在Java开发与数据结构学习中,排序算法是连接基础操作与复杂工程问题的关键环节。理解时间复杂度和空间复杂度的权衡,是评估算法效率的起点。通过剖析冒泡、插入、选择等基础排序的优化思路,再到归并、快排、堆排序的工程级实现,能够帮助开发者针对不同的数据规模、稳定性需求和内存限制做出合理选型。排序算法的价值不止于理论,它广泛应用于海量数据Top K提取、有序序列合并及保持多维字段的业务排序场景。Java中Arrays.sort等内置方法的底层机制也值得深入探究。本文从算法原理出发,结合代码与面试高频考察点,梳理从复
Java排序算法全解析:从手写实现到JDK内置排序
排序算法是计算机程序设计的基石,也是Java开发者面试绕不开的核心考点。从冒泡、插入等基础排序的O(n²)复杂度,到快速排序、归并排序等O(n log n)进阶方案,再到计数排序这类线性时间复杂度算法,不同排序在稳定性、时间与空间复杂度上各有权衡。实际工程中,JDK的Arrays.sort针对基本类型与对象类型分别采用双基准快排与TimSort,体现了算法在真实场景下的优化策略。本文围绕经典排序算法的手写实现与复杂度分析,深入探讨快排优化、堆排序应用、非比较排序适用场景,并解析面试中关于稳定性、最坏情况退化
Java排序算法详解:从基础到进阶,复杂度与稳定性分析
排序算法是数据结构学习中的核心环节,它不仅串联了数组、树、递归等基础知识,更是衡量工程实现与算法效率的关键。在计算机科学中,时间复杂度与稳定性是评估排序算法优劣的两大关键指标,前者决定了算法在大数据量下的执行效率,后者则关乎相同元素在排序后是否保持原有相对顺序。快速排序、归并排序、堆排序等高级算法通过分治思想将时间复杂度优化至O(n log n),但在实际工程选型中,还需结合数据规模、内存占用等场景综合权衡。本文以Java语言为依托,系统梳理冒泡、插入、选择等基础排序,以及快排、归并、堆排等进阶算法的实现原
Java九大排序算法详解:原理、复杂度与面试实战
排序算法是数据结构与算法体系中最基础也最关键的部分,它不仅决定了数据处理的效率,更体现了工程师对问题拆解与资源权衡的思考方式。从比较排序的时间复杂度下界O(n log n),到非比较排序借助数据特征实现的线性时间复杂度,不同算法在稳定性、空间占用和适用场景上各有取舍。冒泡、选择、插入等简单排序奠定了边界控制与交换逻辑的基本功;快排、归并、堆排序则展示了分治思想和堆结构的工程价值;计数、桶、基数排序更是在特定数据分布下实现了降维打击。实际开发中,Arrays.sort的底层实现、TopK问题求解、多字段稳定排
Java之美[从菜鸟到高手演变]之常见的几种排序算法-插入、选择、冒泡、快排、堆排等
解决了上面的合并有序数列问题,再来看归并排序,其的基本思路就是将数组分成二组A,B,如果这二组组内的数据都是有序的,那么就可以很方便的将这二组数据进行排序。设置两个指针:i和j,分别指向第一个和最后一个,i像后移动,j向前移动,选第一个数为标准(一般这样做,当然快排的关键就是这个“标准”的选取),从后面开始,找到第一个比标准小的数,互换位置,然后再从前面,找到第一个比标准大的数,互换位置,第一趟的结果就是标准左边的都小于标准,右边的都大于标准(但不一定有序),分成两拨后,继续递归的使用上述方法,最终有序!
【排序算法】插入、选择、堆排、快排、归并、计数
排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。 平时的上下文中,如果提到排序,通常指的是排升序(非降序)。 通常意义上的排序,都是指的原地排序(in place sort) 。 - **稳定性(重要)** 两个相等的数据,如果经过排序后,排序算法能保证其**相对位置不发生变化**,则我们称该算法是具备稳定性的排序算法。 一个稳定的排序,可以实现为不稳定的排序 但是一个本身就不稳定的排序,是不可以变成稳定的排序
排序算法(冒泡、插入、选择、快排、归并)原理动画及Python、Java实现
目前就总结这了,其它的后面看到了再弄。
数据结构-排序(冒泡,选择,插入,希尔,快排,归并,堆排)
假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;当到达=1时,所有记录在统一组内排好序。,与下一个数进行比较,直到找到最大的数,放在n的位置,这是一趟,下一趟还是同样的思路,找到第二大的数,放在n-1的位置,依次下去,总共要走。的区间上找最小的数,在进行交换,也就是有序区间不动,对于无序区间进行比较,依次下去,直至全部有序。
常见的几种排序算法-插入、选择、冒泡、快排、堆排等
Java面试宝典系列之基础排序算法 博客:http://blog.youkuaiyun.com/zhangerqing(转载请说明出处) 本文就是介绍一些常见的排序算法。排序是一个非常常见的应用场景,很多时候,我们需要根据自己需要排序的数据类型,来自定义排序算法,但是,在这里,我们只介绍这些基础排序算法,包括:插入排序、选择排序、冒泡排序、快速排序(重点)、堆排序、归并排序等等。看
331



被折叠的 条评论
为什么被折叠?



