JAVA ---- 经典排序算法

目录

一. 插入排序

1.  直接插入排序 

 代码演示

2.希尔排序( 缩小增量排序 )

二. 选择排序 

1.直接选择排序 

代码: 

2. 堆排序 

代码 

三.  交换排序 

1. 冒泡排序 

代码 

2.  快速排序 

代码(有注释): 


动图来自网路 

一. 插入排序

1.  直接插入排序
 

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 

由上图可清晰的看到,如何直接插入,从第二个(下标为 1 )开始 ,向前比较,以此类推

 代码演示

/*** 插入排序* @param array*/public static void insertSort(int[] array){for (int i = 1; i < array.length; i++) {int tmp = array[i];int j = i - 1;for (j = i - 1; j >= 0 ; j--) {if(array[j] > tmp){//就是让大的往后挪array[j + 1] = array[j];}else {break;}}array[j + 1] = tmp;}}

直接插入总结:
1. 元素集合越接近有序,直接插入排序算法的时间效率越高
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:稳定

2.希尔排序( 缩小增量排序 )

先选定一个整数,把待排序文件中所有记录分成多个组,所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达gap=1时,所有记录在统一组内排好序 

 

/*** 希尔排序* @param array*/public static void shellSort(int[] array){int gap = array.length;//增量while(gap > 1){gap = gap/2;shell(array, gap);}}private static void shell(int[] array, int gap){for (int i = gap; i < array.length; i++) {int tmp = array[i];int j = i - gap;for(; j >= 0; j-=gap){if(array[j] > tmp){array[j + gap] = array[j];}else {break;}}array[j + gap] = tmp;}}

希尔排序总结:
1. 希尔排序是对直接插入排序的优化。
2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。
3. 希尔排序的时间复杂度不好计算,(
O(n^1.3) ~O(n^1.5))因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定。 

4.不稳定

二. 选择排序
 

1.直接选择排序
 

每一次从待排序的数据元素中选出最小(或最大)的一个元素,存放在序列的起始位置,直到全部待排序的数据元素排完。

   

代码: 

/*** 选择排序* @param array*/public static void selectSort(int[] array) {int i = 0;for(i = 0; i < array.length; i++){int minIndex = i;int j = i + 1;for(j = i + 1; j < array.length; j++){if(array[minIndex] > array[j]){minIndex = j;}}int tmp = array[i];array[i] = array[minIndex];array[minIndex] = tmp;}}

直接选择排序总结:
1. 直接选择排序,效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定 

2. 堆排序 

堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。 

简单来说,把数组变成大根堆,之后让第一个和最后一个交换,然后再把换后的变成大根堆,这样最大的就都再后面了 

代码 

/*** 堆排序* 把数组变成大根堆,之后让第一个和最后一个交换,然后再把换后的变成大根堆,这样最大的就都再后面了* @param array*/public static void heapSort(int[] array){int end = array.length - 1;for (int parent = (array.length - 1 - 1) / 2; parent >= 0; parent--) {//和孩子节点换shiftDown(parent, array.length, array);}while (end > 0){swap(array, 0, end);shiftDown(0, end, array);end--;}}private static void swap(int[] array, int begin, int end){int tmp = array[begin];array[begin] = array[end];array[end] = tmp;}private static void shiftDown(int parent,int usedSize,int[] array) {int child = (2*parent) + 1;//左孩子节点//不越界while (child < usedSize){//先比较一下孩子们的大小,找到当中最大的if(child + 1 < usedSize && array[child] < array[child + 1]){child = child + 1;}//然后再和parent比较大小if(array[child] > array[parent]){swap(array,child, parent);//比完一组,parent得往下走,动起来parent = child;child = (2*parent) + 1;}else {break;}}}

 序总结:
1. 时间复杂度:O(nlogn)
2. 空间复杂度:O(1)
3. 稳定性:不稳定 

三.  交换排序
 

1. 冒泡排序 

这应该是我们最早接触的一种排序,很好理解,不说了 (以前写过)

代码 

/*** 冒泡排序* @param array*/public static void bubbleSort(int[] array){for (int i = 0; i < array.length - 1; i++) {boolean flg = false;for (int j = 0; j < array.length - 1 - i; j++) {if(array[j] > array[j+1]){int tmp = array[j];array[j] = array[j+1];array[j+1] = tmp;flg = true;}}if(!flg){break;}}}

冒泡排序总结
1. 时间复杂度:O(N^2)
2. 空间复杂度:O(1)
3. 稳定性:稳定 

2.  快速排序
 

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。 

代码(有注释): 

下面介绍两种常用找基准方法 

1.Hoare版 

看上图,直到key(也就是6) 的左边都比key小,右边都比key大

/*** 快速排序* @param array*/public static void quickSort(int[] array){quick(array, 0, array.length - 1);}private static void quick(int[] array, int start, int end){if(start >= end){return;}//防止出现都在一边的情况int index = midOfThree(array, start, end);//找到这三个数里(start, mid, end)第二大的下标swap(array, start, index);//让start处是这三个里第二大的数//找到基准int pivot = partition(array, start, end);quick(array, start, pivot - 1);quick(array, pivot + 1, end);}private static int partition(int[] array, int left, int right){int key = array[left];int i = left;while(left < right){//左边的都比key小,右边的都比key大//必须right先走,因为如果是left先走的话,left哪里一定是一个大于key的数,因为left遇到大于key的数才停,之后和right相遇,再换,//那左边的被交换数一定是一个大于key的数//因为右边应该都是大于key的值,所以要把小于key的数抓出来while (left < right && array[right] >= key){right--;}//同理while(left < right && array[left] <= key){left++;}swap(array, left, right);}swap(array, i, left);return left;}private static int midOfThree(int[] array, int left, int right){int mid = (left + right)/2;if(array[left] > array[right]){if(array[mid] > array[left]){return left;}else if(array[mid] < array[right]){return right;}else {return mid;}}else {if(array[mid] > array[right]){return right;}else if(array[mid] < array[left]){return left;}else {return mid;}}}
}

2.挖坑法 

 

看上图,直到走完,把pivot按到最后空出的位置,这样 左边都pivot比小,右边都比pivot大了

private static int partition(int[] array, int left, int right) {int i = left;int j = right;int pivot = array[left];//坑挖出来了while (i < j) {while (i < j && array[j] >= pivot) {j--;} array[i] = array[j];//坑位变成[j]while (i < j && array[i] <= pivot) {i++;} array[j] = array[i];//坑位变成[i]} array[i] = pivot;return i;
}

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

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

相关文章

ubuntu创建多用户并使用ssh链接

添加多个同时登录的用户 以下内容中的“username”根据自己需求自己定义 1.创建新用户 sudo useradd username2.给新用户添加管理权限 sudo vim /etc/sudoers打开的文件中添加如下内容 username ALL(ALL:ALL) ALL3.设置密码 输入&#xff1a; sudo passwd username打开的…

「软件测试」最全面试问题和回答,全文背熟不拿下offer算我输

一般要应聘关于测试的工作&#xff0c;面试题会不会很难?下面小编整理了软件测试面试题及答案&#xff0c;欢迎参考! 一、引言 1.1 文档目的 本次文档是为了收集在面试中遇到的一问题与常见的一些答案并不是唯一答案 二、职业规划 2.1 简单的自我介绍下 面试宫&#xff…

点大商城V2_2.5.0 全开源版 商家自营+多商户入驻 百度+支付宝+QQ+头条+小程序端+unipp开源前端安装测试教程

播播资源安装点大商城V2_2.5.0 全开源版测试后发现后台总体体验下来比较简洁&#xff0c;营销功能还是挺多该有的都有了&#xff0c;相比上一版优化很多细节。首页和会员中心均支持DIY装修&#xff0c;底部菜单也一样&#xff0c;安装测试中目前未发现BUG&#xff0c;小程序整体…

etcd实现大规模服务治理应用实战

导读&#xff1a;服务治理目前越来越被企业建设所重视&#xff0c;特别现在云原生&#xff0c;微服务等各种技术被更多的企业所应用&#xff0c;本文内容是百度小程序团队基于大模型服务治理实战经验的一些总结&#xff0c;同时结合当前较火的分布式开源kv产品etcd&#xff0c;…

文献阅读笔记——求解车辆路径问题及其变体的元启发式算法的分类综述

论文题目&#xff1a;A taxonomic review of metaheuristic algorithms for solving the vehicle routing problem and its variants 其他信息&#xff1a;Computers & Industrial Engineering|2020|Raafat Elshaer⁎, Hadeer Awad 文章贡献&#xff1a;1&#xff09;对使…

如何用Python搭建监控平台

监控和运维&#xff0c;是互联网工业链上非常重要的一环。监控的目的就是防患于未然。通过监控&#xff0c;我们能够及时了解到企业网络的运行状态。一旦出现安全隐患&#xff0c;你就可以及时预警&#xff0c;或者是以其他方式通知运维人员&#xff0c;让运维监控人员有时间处…

什么是计算机蠕虫?

计算机蠕虫诞生的背景 计算机蠕虫的诞生与计算机网络的发展密切相关。20世纪60年代末和70年代初&#xff0c;互联网还处于早期阶段&#xff0c;存在着相对较少的计算机和网络连接。然而&#xff0c;随着计算机技术的进步和互联网的普及&#xff0c;计算机网络得以迅速扩张&…

S32 Design Studio for ARM(S32DS)下载和安装

1. S32 Design Studio for ARM 介绍 S32 Design Studio for ARM&#xff08;下面简称S32DS&#xff09;&#xff0c;是 NXP 官方在 2014 年官方推出的&#xff0c;专门面向 S32K、KEA、MAC57D54H等系列微控制器的集成开发环境。 S32DS是由Eclipse和一些插件集成而来的开发平台…

kafka消息队列最常用的两种模式,以及应用场景

目录 一、发布-订阅模式 二、点对点模式 三、应用场景 一、发布-订阅模式 发布-订阅模式是最常见的消息传递模式&#xff0c;其中消息发布者将消息发送到一个或多个主题&#xff08;Topic&#xff09;&#xff0c;而订阅者可以选择订阅一个或多个主题来接收消息。每个订阅者…

实现本地缓存-caffeine

目录 实现caffeine cache CacheManager Caffeine配置说明 创建自定义配置类 配置缓存管理器 编写自动提示配置文件 测试使用 创建测试配置实体类 创建测试配置类 创建注解扫描的测试实体 创建单元测试类进行测试 实现caffeine cache CacheManager SimpleCacheManag…

香橙派4和树莓派4B构建K8S集群实践之七: Jenkins

目录 1. 说明 2. 步骤 2.1 准备工作 2.2 安装 2.2.1 用jenkins原站for k8s的安装仓方法安装 2.2.2 Helm 安装 3. 相关命令 4. 遇到的问题 5. 参考 1. 说明 在k8s上部署jenkins&#xff0c;并用 jenkins.k8s-t2.com访问在namespace为devops下安装在指定节点k8s-master-…

欧姆龙以太网模块如何设置ip连接 Kepware opc步骤

在数字化和自动化的今天&#xff0c;PLC在工业控制领域的作用日益重要。然而&#xff0c;PLC通讯口的有限资源成为了困扰工程师们的问题。为了解决这一问题&#xff0c;捷米特推出了JM-ETH-CP转以太网模块&#xff0c;让即插即用的以太网通讯成为可能&#xff0c;不仅有效利用了…

字符函数和字符串函数上篇(详解)

❤️ 作者简介 &#xff1a;RO-BERRY 致力于C、C、数据结构、TCP/IP、数据库等等一系列知识&#xff0c;对纯音乐有独特的喜爱 &#x1f4d7; 日后方向 : 偏向于CPP开发以及大数据方向&#xff0c;如果你也感兴趣的话欢迎关注博主&#xff0c;期待更新 字符函数和字符串函数 &a…

OpenCV——总结《车牌识别》

1.图片中的hsv hsv提取蓝色部分 # hsv提取蓝色部分 def hsv_color_find(img):img_copy img.copy()cv2.imshow(img_copy, img_copy)"""提取图中的蓝色部分 hsv范围可以自行优化cv2.inRange()参数介绍&#xff1a;第一个参数&#xff1a;hsv指的是原图第二个参…

初识vue3/setup/ ref()/ computed/watch/生命周期/父传子

创建项目先不着急学 main.js变了 新加setup reactive ref() computed watch 生命周期 父传子 子传父 ref/模板引用 暴露子组件属性 跨层传数据 defineOptions

用OpenCV进行图像分割--进阶篇

1. 引言 大家好&#xff0c;我的图像处理爱好者们&#xff01; 在上一篇幅中&#xff0c;我们简单介绍了图像分割领域中的基础知识&#xff0c;包含基于固定阈值的分割和基于OSTU的分割算法。这一次&#xff0c;我们将通过介绍基于色度的分割来进一步巩固大家的基础知识。 闲…

【JavaEE】DI与DL的介绍-Spring项目的创建-Bean对象的存储与获取

Spring的开发要点总结 文章目录 【JavaEE】Spring的开发要点总结&#xff08;1&#xff09;1. DI 和 DL1.1 DI 依赖注入1.2 DL 依赖查询1.3 DI 与 DL的区别1.4 IoC 与 DI/DL 的区别 2. Spring项目的创建2.1 创建Maven项目2.2 设置国内源2.2.1 勾选2.2.2 删除本地jar包2.2.3 re…

C++万字自学笔记

[TOC] 一、 C基础 C的IDE有CLion、Visual Studio、DEV C、eclipse等等&#xff0c;这里使用CLion进行学习。 0. C初识 0.1 第一个C程序 编写一个C程序总共分为4个步骤 创建项目创建文件编写代码运行程序 #include <iostream>int main() {using namespace std;cout…

Vant源码解析(四)----Popup弹出层,详解样式方法

这个功能&#xff0c;自己也手写过&#xff0c;毕竟有很多弹窗的嘛。 我自己写就是&#xff1a;一个背景层&#xff0c;然后一个盒子里面放内容。再写个显示隐藏事件。够够的了。 Vant的Popup弹出层 页面结构 短短一个背景加内容盒子&#xff0c;vant套了几层。 这是引用的组件…

数据结构单向循环链表,创建以及增删改查的实现

一、单向循环链表的描述 循环链表&#xff1a;是另一种形式的链式存储结构。其特点是表中最后一个结点的指针域指向头节点&#xff0c;整个链表形成一个环。 单向循环链表的操作和单链表操作基本一致&#xff0c;差别在于&#xff1a;当链表遍历时&#xff0c;判别当前指针p是…