常用的排序算法

1. 快速排序

1.1 基本思想:

通过一趟排序将要排序的数据分割成独立的两部分,其中一部分的所有数据都比另外一部分的所有数据要小,然后再按此方法对这两部分数据分别进行快速排序,整个排序过程可以递归进行,以此达到整个数据变成有序序列。

1.2 步骤如下:

  1. 选择基准(Pivot):在数据集之中,选择一个元素作为"基准"(pivot)
  2. 分区(Partitioning):将数组进行分区(partition),将小于基准值的元素移到基准的左边,大于基准值的元素移到基准的右边。分区完成后,基准元素所处的位置就是最终排序后它的位置
  3. 递归排序:递归地将小于基准值元素的子序列和大于基准值元素的子序列排序

快速排序在最坏情况下的时间复杂度为O( n 2 n^2 n2),但这种情况非常少见。它的平均时间复杂度为O( n l o g n n log n nlogn),并且由于排序过程是在原地进行分区,所以它不需要额外的存储空间,空间复杂度为O( l o g n log n logn)

1.3代码实现:

// 快速排序主方法
public static void quickSort(int[] arr, int low, int high) {if (low < high) {// 分区操作,获取基准元素位置int pivotIndex = partition(arr, low, high);// 递归排序基准左侧子数组quickSort(arr, low, pivotIndex - 1);// 递归排序基准右侧子数组quickSort(arr, pivotIndex + 1, high);}
}// 分区方法
private static int partition(int[] arr, int low, int high) {int pivot = arr[low]; // 选择第一个元素作为基准int i = low;int j = high;while (i < j) {// 从右向左找第一个小于基准的元素while (i < j && arr[j] >= pivot) {j--;}if (i < j) {arr[i++] = arr[j];}// 从左向右找第一个大于基准的元素while (i < j && arr[i] < pivot) {i++;}if (i < j) {arr[j--] = arr[i];}}// 将基准元素放到正确位置arr[i] = pivot;return i;
}

2. 归并排序

2.1 基本思想:

将数组分成若干个小组,先在每个小组内部进行排序,然后将有序的小组合并成更大的有序组,直到整个数组变得有序

2.2 步骤如下:

  1. 分解(Divide):将原始数组切分成较小的数组,直到每个小数组只有一个位置,这时每个小数组都是有序的
  2. 合并(Conquer):将小数组两两合并,保证合并后的数组仍然有序。这一步是通过比较每个小数组中的元素来完成的
  3. 重复:重复上述合并操作,直到最终合并成一个有序的数组

归并排序的时间复杂度是 O( n l o g n n log n nlogn),这是因为数组每次都被分成两半(这是一个 l o g n log n logn的过程),并且在合并过程中需要遍历所有元素(这是一个 n n n 的过程)。此外,归并排序不是原地排序算法,因为它需要额外的存储空间来合并数组。

2.3 代码实现:

// 归并排序主方法(递归实现)
public static void mergeSort(int[] arr, int left, int right) {if (left < right) {int mid = (left + right) / 2;// 递归排序左半部分mergeSort(arr, left, mid);// 递归排序右半部分mergeSort(arr, mid + 1, right);// 合并两个有序子数组merge(arr, left, mid, right);}
}// 合并两个有序子数组的方法
private static void merge(int[] arr, int left, int mid, int right) {int n1 = mid - left + 1;int n2 = right - mid;// 创建临时数组存储左右子数组int[] leftArr = new int[n1];int[] rightArr = new int[n2];System.arraycopy(arr, left, leftArr, 0, n1);System.arraycopy(arr, mid + 1, rightArr, 0, n2);// 合并临时数组到原数组int i = 0, j = 0, k = left;while (i < n1 && j < n2) {if (leftArr[i] <= rightArr[j]) {arr[k++] = leftArr[i++];} else {arr[k++] = rightArr[j++];}}// 复制左子数组剩余元素while (i < n1) {arr[k++] = leftArr[i++];}// 复制右子数组剩余元素while (j < n2) {arr[k++] = rightArr[j++];}
}

3. 插入排序

3.1 基本思想:

通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入

3.2 步骤如下:

  1. 从第一个元素开始,该元素可以认为已经被排序
  2. 取出下一个元素,在已经排序的元素序列中从后向前扫描
  3. 如果该元素(已排序)大于新元素,将该元素移到下一位置
  4. 重复步骤3,直到找到已排序的元素小于或者等于新元素的位置
  5. 将新元素插入到该位置后
  6. 重复步骤2~5

插入排序的时间复杂度在最坏情况下是 O( n 2 n^2 n2),平均情况也是 O( n 2 n^2 n2),但在数组几乎排序好的情况下,它可以达到 O( n n n)

3.3 代码实现:

public static void insertionSort(int[] array) {int n = array.length;for (int i = 1; i < n; i++) {int key = array[i];int j = i - 1;// 将array[i]与已排序好的array[0...i-1]中的元素进行比较,找到合适的位置插入while (j >= 0 && array[j] > key) {array[j + 1] = array[j];j = j - 1;}array[j + 1] = key;}
}

4. 冒泡排序

4.1 基本思想:

重复地遍历要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。遍历数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端

4.2 步骤如下:

  1. 比较相邻的元素。如果第一个比第二个大(升序排序),就交换它们两个
  2. 对每一对相邻元素做同样的工作,从开始第一对到结尾的最后一对。在这一点,最后的元素应该会是最大的数
  3. 针对所有的元素重复以上的步骤,除了最后一个
  4. 重复步骤1~3,直到排序完成

冒泡排序的时间复杂度是O( n 2 n^2 n2),因为它需要比较所有相邻的元素对,并且在最坏的情况下需要交换所有的元素

4.3 代码实现:

// 基础冒泡排序实现
public static void bubbleSort(int[] arr) {if (arr == null || arr.length == 0) {return;}int n = arr.length;for (int i = 0; i < n - 1; i++) {for (int j = 0; j < n - 1 - i; j++) {if (arr[j] > arr[j + 1]) {// 交换元素int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;}}}
}// 优化版冒泡排序(带标志位)
public static void optimizedBubbleSort(int[] arr) {if (arr == null || arr.length == 0) {return;}int n = arr.length;boolean swapped;for (int i = 0; i < n - 1; i++) {swapped = false;for (int j = 0; j < n - 1 - i; j++) {if (arr[j] > arr[j + 1]) {// 交换元素int temp = arr[j];arr[j] = arr[j + 1];arr[j + 1] = temp;swapped = true;}}// 如果一轮没有交换,提前结束if (!swapped) {break;}}
}

5. 选择排序

5.1 基本思想:

首先在未排序序列中找到最小(或最大)元素,存放到排序序列的起始位置,然后再从剩余未排序元素中继续寻找最小(或最大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕

5.2 步骤如下:

  1. 在未排序序列中找到最小(或最大)元素
  2. 将其与未排序序列的第一个元素交换位置
  3. 在剩余未排序元素中重复上述步骤,直到整个序列排序完成

选择排序的时间复杂度无论是最好、平均还是最坏情况都是 O( n 2 n^2 n2)

5.3 代码实现:

// 选择排序主方法
public static void selectionSort(int[] arr) {int n = arr.length;for (int i = 0; i < n - 1; i++) {int minIndex = i;// 寻找未排序部分的最小元素索引for (int j = i + 1; j < n; j++) {if (arr[j] < arr[minIndex]) {minIndex = j;}}// 交换当前元素与找到的最小元素if (minIndex != i) {int temp = arr[i];arr[i] = arr[minIndex];arr[minIndex] = temp;}}
}

以上就是常用的一些排序算法,虽然Java中有排序的方法,但是这些方法还是需要了解和掌握。

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

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

相关文章

【黑马点评】Redis解决集群的session共享问题

由于不同的tomcat服务器之间的session是不共享的&#xff0c;当请求如果在不同tomcat服务器之间切换就会导致数据丢失的问题。 使用redis可以解决session数据共享的问题 redis是tomcat以外的存储&#xff0c;存在redis中的数据&#xff0c;任何一台tomcat都能看得见&#xff0…

淘宝客户端动态化页面搭建

在手机淘宝等高频更新的业务场景中&#xff0c;UI页面的动态化和快速交付成为技术团队面临的重要挑战。本文围绕“客户端动态化页面搭建”这一主题&#xff0c;深入探讨了如何通过抽象框架设计解决高动态化页面的快速构建问题。文章详细介绍了框架的核心模块&#xff08;如Data…

无人机,雷达定点飞行时,位置发散,位置很飘,原因分析

参考&#xff1a; 无人车传感器 IMU与GPS数据融合进行定位机制_gps imu 组合定位原始数-CSDN博客 我的无人机使用雷达定位&#xff0c;位置模式很飘 雷达的更新频率也是10HZ&#xff0c; 而px飞控的频率是100HZ&#xff0c;没有对两者之间的频率差异做出处理 所以才导致无人…

Postman 版本信息速查:快速定位版本号

保持 Postman 更新至最新版本是非常重要的&#xff0c;因为这能让我们享受到最新的功能&#xff0c;同时也保证了软件的安全性。所以&#xff0c;如何快速查看你的 Postman 版本信息呢&#xff1f; 如何查看 Postman 的版本信息教程

Object结构

Object结构 参考博客

数据分析概述

数据分析&#xff1a;用适当的分析方法和挖掘方法对收集来的数据进行研究总结&#xff0c;提取有用的信息&#xff0c;形成结论并支持决策的过程。 一.数据分析的分类 1.业务描述性分析。以数据为分析对象&#xff0c;以探索数据内的有用信息为主要途径&#xff0c;以解决业务…

ubuntu下终端打不开的排查思路和解决方法

问题现象描述&#xff1a;ubuntu开机后系统桌面显示正常&#xff0c;其他图形化的app也都能打开无异常&#xff0c;唯独只有terminal终端打不开&#xff0c;无论是鼠标点击终端软件&#xff0c;还是ctrlaltt&#xff0c;还是altF2后输入gnome-terminal后按回车&#xff0c;这三…

第一天 Linux驱动程序简介

目录 一、驱动的作用 二、裸机驱动 VS linux驱动 1、裸机驱动 2、linux驱动 三、linux驱动位于哪里&#xff1f; 四、应用编程 VS 内核编程 1、共同点 2、不同点 五、linux驱动分类 1、字符设备 2、块设备 3、网络设备 六、Linux驱动学习难点与误区 1、学习难点 …

探索抓包利器ProxyPin,实现手机APP请求抓包,支持https请求

以下是ProxyPin的简单介绍&#xff1a; - ProxyPin是一个开源免费HTTP(S)流量捕获神器&#xff0c;支持 Windows、Mac、Android、IOS、Linux 全平台系统- 可以使用它来拦截、检查并重写HTTP(S)流量&#xff0c;支持捕获各种应用的网络请求。ProxyPin基于Flutter开发&#xff0…

Windows中安装git工具

下载好git安装包 点击next 选择安装目录 根据需要去勾选 点击next 点击next PATH环境选择第二个【Git...software】即可&#xff0c;再点击【Next】。 第一种配置是“仅从Git Bash使用Git”。这是最安全的选择&#xff0c;因为您的PATH根本不会被修改。您只能使用 Git Bash 的…

Banner区域

div下 justify-content:space-between 左侧测导航left 在这里插入图片描述 在这里插入图片描述

STM32 IIC通信

目录 IIC简介硬件电路连接I2C时序基本单元IIC完整数据帧MPU6050封装硬件IIC内部电路 IIC简介 IIC&#xff08;Inter-Integrated Circuit&#xff09;是 IIC Bus 简称&#xff0c;中文叫集成电路总线。它是一种串行通信总线&#xff0c;使用多主从架构&#xff0c;由飞利浦公司…

蓝桥杯嵌入式学习笔记

用博客来记录一下参加蓝桥杯嵌入式第十六届省赛的学习经历 工具环境准备cubemx配置外部高速时钟使能设置串口时钟配置项目配置 keil配置烧录方式注意代码规范头文件配置 模块ledcubemx配置keil代码实现点亮一只灯实现具体操作的灯&#xff0c;以及点亮还是熄灭 按键cubemx配置k…

体育比分网站开发避坑指南:如何选择靠谱的数据服务商?(10年行业经验总结,避免踩坑!)

作为一家专业的体育比分数据服务商&#xff0c;我们接触过大量客户&#xff0c;发现很多人在开发体育比分网站或接入数据API时&#xff0c;由于选择不靠谱的服务商&#xff0c;导致项目延期、数据延迟、售后无响应、隐性收费等问题&#xff0c;最终影响运营效果&#xff0c;甚至…

VLAN综合实验二

一.实验拓扑&#xff1a; 二.实验需求&#xff1a; 1.内网Ip地址使用172.16.0.0/分配 2.sw1和SW2之间互为备份 3.VRRP/STP/VLAN/Eth-trunk均使用 4.所有Pc均通过DHCP获取IP地址 5.ISP只能配置IP地址 6.所有…

ABAP FPM

1.效果 2.查询条件的feed class SE11创建feed class数据的结构 ZCL_FPM_FIFO_SEARCH GET_DEFINITION方法代码 METHOD if_fpm_guibb_search~get_definition.eo_field_catalog_attr ? cl_abap_structdescr>describe_by_name( ZSS_FIFO_DATA ).ENDMETHOD. PROCESS_EVENT代码…

某大麦手机端-抢票

引言 仅供学习研究&#xff0c;欢迎交流 抢票难&#xff0c;难于上青天&#xff01;无论是演唱会、话剧还是体育赛事&#xff0c;大麦网的票总是秒光。作为一名技术爱好者&#xff0c;你是否想过用技术手段提高抢票成功率&#xff1f;本文将为你揭秘大麦手机端抢票的核心技术…

【免费】2007-2019年各省地方财政文化体育与传媒支出数据

2007-2019年各省地方财政文化体育与传媒支出数据 1、时间&#xff1a;2007-2019年 2、来源&#xff1a;国家统计局、统计年鉴 3、指标&#xff1a;行政区划代码、地区、年份、地方财政文化体育与传媒支出 4、范围&#xff1a;31省 5、指标说明&#xff1a;地方财政在文化、…

Playwright从入门到实战:比Selenium更快的数据爬取案例实战

摘要 Playwright 是微软开源的下一代浏览器自动化工具&#xff0c;凭借其高性能、跨浏览器支持和现代化设计&#xff0c;迅速成为 Web 自动化领域的热门选择。本文将从 安装配置 开始&#xff0c;通过 实战演练 展示其核心功能&#xff0c;并与 Selenium 深度对比&#xff0c;…

音频知识 参数分析

通道布局 参考 通过pcm音频数据计算分贝 理解FFT和信号加窗原理及意义 dts音效大师教程