Java 数据结构与算法系列精讲之排序算法
作者:我是小白呀 发布时间:2023-11-01 13:25:40
概述
从今天开始, 小白我将带大家开启 Java 数据结构 & 算法的新篇章.
冒泡排序
冒泡排序 (Bubble Sort) 是一种简单的排序算法. 它重复地遍历要排序的数列, 一次比较两个元素, 如果他们的顺序错误就把他们交换过来. 遍历数列的工作是重复地进行直到没有再需要交换, 也就是说该数列已经排序完成. 这个算法的名字由来是因为越小的元素会经由交换慢慢 “浮” 到数列的顶端.
冒泡排序流程:
通过比较相邻的元素, 判断两个元素位置是否需要互换
进行 n-1 次比较, 结尾的元素就会是最大元素
重复以上冒泡过程 n 次
代码实现:
import java.util.Arrays;
public class bubble {
public static void main(String[] args) {
// 创建数据
int[] array = {426,375474,8465,453};
// 实现排序
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(bubbleSort(array)));
}
public static int[] bubbleSort(int[] array) {
// 如果数组为空, 返回
if (array.length == 0){
return array;
}
// 执行冒泡过程n次, n为数组长度
for (int i = 0; i < array.length; i++) {
// 冒泡过程
for (int j = 0; j < array.length - 1 - i; j++) {
// 判断j索引的元素是否比j+1索引的元素大
if (array[j+1] < array[j]) {
// 交换位置
int temp = array[j + 1];
array[j + 1] = array[j];
array[j] = temp;
}
}
}
return array;
}
}
输出结果:
[426, 375474, 8465, 453]
[426, 453, 8465, 375474]
插入排序
插入排序 (Insertion Sort) 是一种简单直观的排序算法. 它的工作原理是通过构建有序序列, 对于未排序数据, 在已排序序列中从后向前扫描,找到相应位置并插入. 插入排序在实现上, 在从后向前扫描过程中, 需要反复把已排序元素逐步向后挪位, 为最新元素提供插入空间.
插入排序流程:
从第二个元素开始, 从后往前扫描
逐个比较元素大小, 之道插入到合适的位置
重复以上步骤 n-1 次
代码实现:
import java.util.Arrays;
public class insert {
public static void main(String[] args) {
// 创建数据
int[] array = {426,375474,8465,453};
// 实现排序
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(insertionSort(array)));
}
public static int[] insertionSort(int[] array) {
// 如果数组为空, 返回
if (array.length == 0)
return array;
// 待排序元素
int current;
// 执行插入过程n-1次
for (int i = 0; i < array.length - 1; i++) {
// 指定待排序元素
current = array[i + 1];
int preIndex = i;
// 执行插入过程, 往前一个个比对
while (preIndex >= 0 && current < array[preIndex]) {
array[preIndex + 1] = array[preIndex];
preIndex--;
}
// 插入元素
array[preIndex + 1] = current;
}
return array;
}
}
输出结果:
[426, 375474, 8465, 453]
[426, 453, 8465, 375474]
归并排序
归并排序 (Merge Sort) 是一种建立在归并操作上的算法, 是分治的一个经典应用.
归并排序流程:
把数组拆分成两个 n/2 长度的子序列
对这两个子序列分别采用归并排序
将排序好的序列合并成最终序列
代码实现:
import java.util.Arrays;
public class merge {
public static void main(String[] args) {
// 创建数据
int[] array = {426,375474,8465,453};
// 实现排序
System.out.println(Arrays.toString(array));
System.out.println(Arrays.toString(mergeSort(array)));
}
public static int[] mergeSort(int[] array) {
// 如果数组长度小于2, 返回
if (array.length < 2) {
return array;
}
// 分治
int mid = array.length / 2;
int[] left = Arrays.copyOfRange(array, 0, mid);
int[] right = Arrays.copyOfRange(array, mid, array.length);
return merge(mergeSort(left), mergeSort(right));
}
public static int[] merge(int[] left, int[] right) {
// 创建数组用于存放合并后的序列
int[] result = new int[left.length + right.length];
for (int index = 0, i = 0, j = 0; index < result.length; index++) {
// 左序列取完
if (i >= left.length)
result[index] = right[j++];
// 右序列取完
else if (j >= right.length)
result[index] = left[i++];
// 左序列的第i个大于有序列的第j个
else if (left[i] > right[j])
result[index] = right[j++];
else
result[index] = left[i++];
}
return result;
}
}
输出结果:
[426, 375474, 8465, 453]
[426, 453, 8465, 375474]
快速排序
快速排序 (Quicksort) 通过一趟排序将要排序的数据分割成独立的两部分, 其中一部分的所有数据都比另外一部分的所有数据都要小, 然后再按此方法对这两部分数据分别进行快速排序, 整个排序过程可以递归进行, 以此达到整个数据变成有序序列.
快速排序流程:
从数组中挑出一个元素作为基准 (Pivot), 通常为第一个或者最后一个元素将比基准元素
小的值放到基准前面, 比基准元素大的值放到基准后面
递归进行分区操作
代码实现:
import java.util.Arrays;
public class quick {
public static void main(String[] args) {
// 创建数据
int[] array = {426, 375474, 8465, 453};
// 实现排序
System.out.println(Arrays.toString(array));
quickSort(array, 0, array.length - 1);
System.out.println(Arrays.toString(array));
}
public static void quickSort(int[] arr, int low, int high) {
// 定义
int p, i, j, temp;
if (low >= high) {
return;
}
// p就是基准数, 每个数组的第一个
p = arr[low];
i = low;
j = high;
while (i < j) {
//右边当发现小于p的值时停止循环
while (arr[j] >= p && i < j) {
j--;
}
//这里一定是右边开始,上下这两个循环不能调换(下面有解析,可以先想想)
//左边当发现大于p的值时停止循环
while (arr[i] <= p && i < j) {
i++;
}
temp = arr[j];
arr[j] = arr[i];
arr[i] = temp;
}
// 交换p和arr[i]
arr[low] = arr[i];
arr[i] = p;
// 分别进行快排
quickSort(arr, low, j - 1);
quickSort(arr, j + 1, high);
}
}
输出结果:
[426, 375474, 8465, 453]
[426, 453, 8465, 375474]
总结
算法 | 时间复杂度 | 稳定性 | 适用场景 |
---|---|---|---|
冒泡排序 | O ( n 2 ) O(n^2) O(n2) | 稳定 | 数组大致为从小到大 |
插入排序 | O ( n 2 ) O(n^2) O(n2) | 稳定 | 适用于数组较小的场景 |
归并排序 | O ( n l o g n ) O(nlogn) O(nlogn) | 稳定 | 适用于数组较大的场景 |
快速排序 | O ( n l o g n ) O(nlogn) O(nlogn) | 不稳定 | 适用于数组较大的场景 |
来源:https://blog.csdn.net/weixin_46274168/article/details/122646957


猜你喜欢
- Java 回调函数概要: 所谓回调,就是客户程序C调用服务程序S中的某个函数A,然后S又在某个时候反过来调用C中的某个
- 1.概述Spring MVC是Spring Framework的一部分,是基于Java实现MVC的轻量级Web框架。Spring MVC的特
- 相信大家在系统学习jvm的时候都会有遇到过这样的问题,散落的jvm知识点知道很多,但是真正在线上环境遇到一些莫名其妙的gc异常时候却无从下手
- 本文实例讲述了C#判断访问来源是否为搜索引擎链接的方法。分享给大家供大家参考。具体分析如下:这段代码通过获取UrlReferrer判断访客是
- 1:什么是Socket所谓套接字(Socket),就是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。一个套接字就是网络上进程通信
- 本文实例为大家分享了Java实现UDP多线程在线咨询,供大家参考,具体内容如下1.发送的线程import java.io.BufferedR
- 本文实例讲述了C#实现DataSet内数据转化为Excel和Word文件的通用类。分享给大家供大家参考,具体如下:前不久因为项目的需要写的一
- System.getProperty()的作用及使用最近在看一些代码时,很多地方都用到了System.getProperty()、Syste
- 在实际的开发中,很多时候还会遇到相对比较复杂的需求,比如产品妹纸或UI妹纸在哪看了个让人兴奋的效果,兴致高昂的来找你,看了之后目的很明确,当
- 案例简述通过C#使用类似QQ窗体的功能,当窗体放置到屏幕的边缘,可以将窗体隐藏,当鼠标再次放置到屏幕边缘时,窗体可再次显示。预备知识导图功能
- 刚学习c#的朋友要自己手动编译c#代码加深记忆,现在总结下如果手动编译!1、先找到系统的.net 环境在一般在 C:\Window
- 今天要介绍一个概念,对象的克隆。本篇有一定难度,请先做好心理准备。看不懂的话可以多看两遍,还是不懂的话,可以在下方留言,我会看情况进行修改和
- 引言在前面的内容中,我们先是一一介绍了Collection集合中都有哪些种类的集合,并且详细地讲解了List集合中的相关知识,那么今天我们来
- 有时间我们在使用多线程的时候,需要取消线程的执行,可以使用CancellationTokenSource来取消对Task开辟多线程的取消如下
- 简述每个项目从新建开始我们或多或少都会导入各种依赖库,如果项目中只有一个module的话,对于依赖库版本的管理很容易,但是多个module的
- 1) async / await使用 async / await 模式,可以在执行代码块操作的时候不会阻塞 UI 或者当前的线程。即使该操作
- 1. 经过简化的Property 早些时候我们这样声明Property private string _myName; public str
- aes 对称加密密钥必须是32字节using System;using System.Security.Cryptography;using
- 后台服务端import java.io.IOException;import java.io.InputStream;import java
- 1. 前言Spring最重要的一个概念当属Bean了,我们写的Controller、Service、Dao凡是加了对应注解交给Spring管