排序-八大排序FollowUp

FollowUp

1.插入排序

(1).直接插入排序

时间复杂度:
最坏情况下:0(n^2)
最好情况下:0(n)
当数据越有序 排序越快

适用于: 待排序序列 已经基本上趋于有序了!
空间复杂度:0(1)
稳定性:稳定的

   public static void insertSort(int[] array){for (int i = 1; i < array.length; i++) {int tmp = array[i];int j = i - 1;for (; j >= 0 ; j--) {//这里加不加等号 和稳定有关系// 但是:本身就是一个稳定的排序 可以实现为不稳定的排序// 但是 本身就是一个不稳定的排序 是不可能变成一个稳定的排序的if(array[j] > tmp){array[j + 1] = array[j];}else {break;}}array[j+1] = tmp;}}

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

重点是最后还是会把整体作一组来直接插入排序

  public static void shellSort(int[] array){int gap = array.length;while(gap > 1){shell(array,gap);gap /= 2;}}public 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;}}

 2.选择排序

(1).直接选择排序

在元素集合array[i]--array[n-1]中选择关键码最大(小)的数据元素
若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第一个)元素交换
在剩余的array[i]--array[n-2](array[i+1]--array[n-1])集合中,重复上述步骤,直到集合剩余1个元素

    public static void selectSort(int[] array){for (int i = 0; i < array.length; i++) {int mixIndex = i;for (int j = i+1; j < array.length; j++) {if(array[mixIndex] > array[j]){mixIndex = j;}}int tmp = array[i];array[i] = array[mixIndex];array[mixIndex] = tmp;}}

【直接选择排序的特性总结】
1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
2. 时间复杂度:O(N^2)
3. 空间复杂度:O(1)
4. 稳定性:不稳定

(2.)双向选择排序:

 public static void selectSort2(int[] array){int left = 0;int right = array.length-1;while(left < right){int minIndex = left;int maxIndex = left;for (int i = left+1; i < right; i++) {if(array[i] > array[maxIndex]){maxIndex = i;}if(array[i] < array[minIndex]){minIndex = i;}swap(array,left,minIndex);//防止最大的是在第一个的时候if(maxIndex == left){maxIndex = minIndex;}swap(array,right,maxIndex);left++;right--;}}}

(3).堆排序

具体的思路在PriorityQueue(一)——用堆实现优先级队列

    public static void heapSort(int[] array){creatHeap(array);int end = array.length-1;while(end > 0){swap(array,0,end);siftDown(array,0,end);end--;}}private static void creatHeap(int[] array) {for (int parent = (array.length-1-1)/2; parent >= 0 ; parent--) {siftDown(array,parent,array.length);}}private static void siftDown(int[] array,int parent,int len) {int child = 2*parent + 1;while(child < len){if(child +1 < len && array[child] < array[child+1]){child++;}if(array[child] > array[parent]){swap(array,child,parent);parent = child;child = 2*parent + 1;}else {break;}}}
public static void swap(int[] array, int i, int j){int tmp = array[i];array[i] = array[j];array[j] = tmp;}

3.交换排序

(1).冒泡排序

优化:

时间复杂度:0(N^2)
如果加了优化:最好情况下 可以达到0(n)

空间复杂度:0(1)

稳定性:稳定的排序
优化:每一趟都需要判断 上一趟 有没有交换

    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]){swap(array,j,j+1);flg =true;}}//说明上一趟没有交换,也就是有序了if(!flg){break;}}}public static void swap(int[] array, int i, int j){int tmp = array[i];array[i] = array[j];array[j] = tmp;}

(2).快速排序 

 
时间复杂度
最好的情况下:0(N*logN) 最坏情况下:0(N^2)逆宇|有序空间复杂度:
最好的情况下:0(logN) 最坏情况下:0(N)逆序/有序
稳定性:不稳定

快排最好和最坏情况分析

Hoare法

记录下key L和R相向出发,R找比Key小的值,L找比Key大的值,R先找找到后,L再找,两个找到交换;直到L和R相遇,相遇的位置为最后L找到的小于Key的值(让R先找的原因),此时的L就是pivot ,将Key和L交换

然后以pivot为中点,将它左右两边的循环以上操作也就是递归直到传入的L和R为相同的,那么任何一个以pivot为中点的数组都变成有序的了

pivot指的是l和r相遇的位置 

  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 pivot = partitionHoare(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static int partitionHoare(int[] array, int left, int right) {int tmp = array[left];int i = left;while(left < right){while(left < right && array[right] >= tmp){right--;}while (left < right && array[left] <= tmp){left++;}swap(array,left,right);}swap(array,i,left);return left;}

总结:

 

 

 挖坑法

向将L的第一个位置为key,也就是坑位置,然后还是R先走找到比key小的就将R下标的值给坑位,此时R为坑位,L再走,找到比L大的值,放到坑位,L此时变为坑位,直到R和L相遇,还是保证L和R相遇的时候,是R找的比Key小的放到坑位里,然后将相遇的坑位放入Key

   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 pivot = partitionHole(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static int partitionHole(int[] array, int left, int right) {int tmp = array[left];int t = left;while(left < right){while(left < right && array[right] >= tmp){right--;}array[left] = array[right];while (left < right && array[left] <= tmp){left++;}array[right] = array[left];}array[left] = tmp;return left;}

总结: 

前后指针法

cur指向left加1的位置,prev指向left的位置,cur往前走,当遇到一个小于left下标值,并且此时cur和prev指向的不是同一个位置,那么cur和prev下标的值互换,直到cur超过right此时将prev和left下标的值互换,并返回prev,即是相对的中间位置

 public static void quickSort(int[] array) {quick(array, 0, array.length - 1);}
public static int partition(int[] array, int left, int right){int prev = left;int cur = left + 1;while (cur <= right){if(array[cur] < array[left] && array[++prev] != array[cur]){swap(array,prev,cur);}cur++;}swap(array,left,prev);return prev;}private static void quick(int[] array,int start,int end) {if(start >= end){return;}if(end - start + 1 <= 15){insertSort(array,start,end);return;}int index = middleNume(array,start,end);swap(array,start,index);int pivot = partition(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}

优化

 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;}if(end - start + 1 <= 15){insertSort(array,start,end);return;}int index = middleNume(array,start,end);swap(array,start,index);int pivot = partitionHoare(array,start,end);quick(array,start,pivot-1);quick(array,pivot+1,end);}private static int middleNume(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;}}}public static void insertSort(int[] array,int left,int right){for (int i = left+1; i <= right; i++) {int tmp = array[i];int j = i - 1;for (; j >= left ; j--) {if(array[j] > tmp){array[j + 1] = array[j];}else {break;}}array[j+1] = tmp;}}

非递归的方法 

  public static void  quickSortNor(int[] array){int start = 0;int end = array.length -1;Stack<Integer> stack =new Stack<>();int pivot = partitionHoare(array,start,end);if(pivot - 1 > start){stack.push(start);stack.push(pivot-1);}if(pivot+1 < end){stack.push(pivot+1);stack.push(end);}while(!stack.empty()){end =stack.pop();start = stack.pop();pivot = partitionHoare(array,start,end);if(pivot - 1 > start){stack.push(start);stack.push(pivot-1);}if(pivot+1 < end){stack.push(pivot+1);stack.push(end);}}}private static int partitionHoare(int[] array, int left, int right) {int tmp = array[left];int i = left;while(left < right){while(left < right && array[right] >= tmp){right--;}while (left < right && array[left] <= tmp){left++;}swap(array,left,right);}swap(array,i,left);return left;}

4. 归并排序

时间复杂度:0(N*logN)

空间复杂度:0(logN)

稳定性:稳定的

排序目前为止3个稳定的排序:直接插入排序、冒泡排序、归并排序

   public static void mergeSort(int[] array){mergeSortFun(array,0,array.length-1);}public static void mergeSortFun(int[] array,int start,int end){if(start >= end){return;}int mid = (start + end)/2;mergeSortFun(array,start,mid);mergeSortFun(array,mid+1,end);//左右两边数组合并merge(array,start,mid,end);}public static void merge(int[] array,int left,int mid, int right){int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;//两边的数组合并数组的长度int[] tmpArray = new int[right - left +1];int k = 0;while (s1 <= e1 && s2 <= e2){if(array[s1] < array[s2]){tmpArray[k++] = array[s1++];}else {tmpArray[k++] = array[s2++];}}while (s1 <= e1){tmpArray[k++] = array[s1++];}while (s2 <= e2){tmpArray[k++] = array[s2++];}for (int i = 0; i < tmpArray.length; i++) {array[left+i] = tmpArray[i];}}

 非递归

   public static void merge(int[] array,int left,int mid, int right){int s1 = left;int e1 = mid;int s2 = mid+1;int e2 = right;//两边的数组合并数组的长度int[] tmpArray = new int[right - left +1];int k = 0;while (s1 <= e1 && s2 <= e2){if(array[s1] < array[s2]){tmpArray[k++] = array[s1++];}else {tmpArray[k++] = array[s2++];}}while (s1 <= e1){tmpArray[k++] = array[s1++];}while (s2 <= e2){tmpArray[k++] = array[s2++];}for (int i = 0; i < tmpArray.length; i++) {array[left+i] = tmpArray[i];}}public static void mergeSortNor(int[] array) {//每组几个数据int gap = 1;while(gap < array.length){for (int i = 0; i < array.length; i = i + gap*2) {int left = i;int mid = left + gap -1;int right = mid + gap;if(mid >= array.length){mid = array.length - 1;}if(right >= array.length){right = array.length - 1;}merge(array,left,mid,right);}gap = gap*2;}}

5.非比较排序

 使用场景是给定一个指定的待排序的序列

    public static void countSort(int[] array){int minVal = array[0];int maxVal = array[0];for (int i = 0; i < array.length; i++){if(array[i] > maxVal){maxVal = array[i];}if(array[i] < minVal){minVal = array[i];}}int len = maxVal - minVal + 1;int[] count = new int[len];for (int i = 0; i < array.length; i++) {count[array[i]-minVal]++;}int index = 0;for (int i = 0; i < array.length; i++) {while(count[0] > 0){array[index] = i + minVal;index++;count[i]--;}}}

 海量数据的排序问题


外部排序:排序过程需要在磁盘等外部存储进行的排序
前提:内存只有 1G,需要排序的数据有 100G
因为内存中因为无法把所有数据全部放下,所以需要外部排序,而归并排序是最常用的外部排序
1. 先把文件切分成 200 份,每个 512 M
2. 分别对 512 M 排序,因为内存已经可以放的下,所以任意排序方式都可以
3. 进行 2路归并,同时对 200 份有序文件做归并过程,最终结果就有序了

 记录当前电脑的时间

long startTime =System.currentTimeMillis();

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

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

相关文章

使用Android Studio 搭建AOSP FrameWork 源码阅读开发环境

文章目录 概述安装Android Studio编译源码使用Android Studio打开源码制作ipr文件直接编译成功后自动打开Android Studio 修改SystemUI验证开发环境 概述 我们都知道Android的系统源码量非常之大&#xff0c;大致有frameworka层源码&#xff0c;硬件层(HAL)源码&#xff0c;内…

能源监控新方案:IEC104转MQTT网关在新能源发电中的应用

需求背景 近些年&#xff0c;我国新能源产业快速发展&#xff0c;光伏、风电等新能源项目高速增长&#xff0c;新能源发电已经成为国家能源结构的重要组成部分。 打造数字化、智能化、信息化的电力物联网系统&#xff0c;实现光伏风电等新能源发电站的远程监控、远程维护是新能…

DRF中的请求入口分析及request对象分析

DRF中的请求入口分析及request对象分析 django restframework框架是在django的基础上又给我们提供了很多方便的功能&#xff0c;让我们可以更便捷基于django开发restful API 1 drf项目 pip install django pip install djangorestframework1.1 核心配置 INSTALLED_APPS [d…

数据库开发关键之与DQL查询语句有关的两个案例

案例 案例1 条件分页查询 查看项目经理提供给我们的需求文档 模糊匹配的含义是 只要包含"张"就可以 use dduo;-- 按照需求完成员工管理的条件分页查询 根据输入条件 查询第一页的数据 每页展示10条记录 -- 输入条件&#xff1a; -- 姓名&#xff1a; 张 -- 年龄&…

【Java】基本程序设计结构(一)

前言&#xff1a;现在&#xff0c;假定已经成功安装了JDK&#xff0c;并且能够运行上篇示例程序。本篇将开始介绍Java程序中的基本设计结构&#xff0c;其中包括&#xff1a;一个简单的Java应用&#xff0c;注释&#xff0c;数据类型&#xff0c;变量与常量&#xff0c;运算符&…

n-Track Studio Suite for Mac激活版:打造您的专属音频工作室

n-Track Studio Suite for Mac是一款功能强大的数字音频工作站软件&#xff0c;让您在家中就能享受到专业录音棚的待遇。无论是录制人声、乐器还是MIDI序列&#xff0c;都能轻松应对。 n-Track Studio Suite for Mac激活版下载 这款软件拥有实时音高校准、时间拉伸和自动补足功…

HT32F52352 -- 解锁电调、电机速度控制

一、问题背景 1.1 硬件&#xff1a; 电池组&#xff0c;电子调速器&#xff08;好盈电调 /ESC&#xff09;&#xff0c;接收机&#xff08;HT32F52352&#xff09;&#xff0c;风扇。 1.2 软件 keil5 二、问题分析 通过1.1图中可知&#xff0c;我们只需要使用 HT32F52352 模拟…

TouchGFX 总结

文章目录 使用中文字体多屏幕间交换数据UI to MCUMCU to UI API文档参考横竖屏切换 使用中文字体 添加一个textArea&#xff0c;默认的英文文本可见&#xff0c;输入中文字体后就看不见了&#xff0c;是因为这个默认的字体不支持中文&#xff0c;改一下字体就可以了&#xff1…

【介绍下有那些常见的ssh功能】

&#x1f3a5;博主&#xff1a;程序员不想YY啊 &#x1f4ab;CSDN优质创作者&#xff0c;CSDN实力新星&#xff0c;CSDN博客专家 &#x1f917;点赞&#x1f388;收藏⭐再看&#x1f4ab;养成习惯 ✨希望本文对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出…

使用mapinfo软件的在线地图插件运行错误解决

使用mapinfo软件的在线地图插件运行错误解决 一、如何解决win10/win11家庭版运行MapInfo中的在线地图插件报错【unexpected error&#xff1b;quitting】问题&#xff1f;二、如何解决在线地图切换地图源时的报错问题&#xff1f; 一、如何解决win10/win11家庭版运行MapInfo中的…

java下乡扶贫志愿者招募管理系统springboot-vue

计算机技术在现代管理中的应用&#xff0c;使计算机成为人们应用现代技术的重要工具。能够有效的解决获取信息便捷化、全面化的问题&#xff0c;提高效率。 技术栈 前端&#xff1a;vue.jsElementUI 开发工具&#xff1a;IDEA 或者eclipse都支持 编程语言: java 框架&#xff1…

vue+element-ui实现横向长箭头,横向线上下可自定义文字(使用after伪元素实现箭头)

项目场景&#xff1a; 需要实现一个长箭头&#xff0c;横向线上下可自定义文字 代码描述 <div><span class"data-model">{{ //上方文字}}</span><el-divider class"q"> </el-divider>//分隔线<span class"data-mod…

【UnityRPG游戏制作】Unity_RPG项目_玩法相关

&#x1f468;‍&#x1f4bb;个人主页&#xff1a;元宇宙-秩沅 &#x1f468;‍&#x1f4bb; hallo 欢迎 点赞&#x1f44d; 收藏⭐ 留言&#x1f4dd; 加关注✅! &#x1f468;‍&#x1f4bb; 本文由 秩沅 原创 &#x1f468;‍&#x1f4bb; 收录于专栏&#xff1a;就业…

Vitis HLS 学习笔记--Schedule Viewer 调度查看器

目录 1. 简介 2. Schedule Viewer详解 2.1 视图说明 2.1.1 Operation\Control Step 2.1.2 周期关系图 2.1.3 Schedule Viewer 菜单栏 2.1.4 属性视图 2.2 内容说明 2.2.1 实参&#xff08;b&#xff09;解释 2.2.2 实参&#xff08;a&#xff09;解释 2.2.3 变量&am…

【C++】详解STL的容器之一:list

目录 简介 初识list 模型 list容器的优缺点 list的迭代器 常用接口介绍 获取迭代器 begin end empty size front back insert push_front pop_front push_back pop_back clear 源代码思路 节点设计 迭代器的设计 list的设计 begin() end() 空构造 ins…

C# Web控件与数据感应之 TreeView 类

目录 关于 TreeView 一些区别 准备数据源 范例运行环境 一些实用方法 获取数据进行呈现 ​根据ID设置节点 获取所有结点的索引 小结 关于 TreeView 数据感应也即数据捆绑&#xff0c;是一种动态的&#xff0c;Web控件与数据源之间的交互&#xff0c;本文将继续介绍与…

C#技巧之同步与异步

区别 首先&#xff0c;同步就是程序从上往下顺序执行&#xff0c;要执行完当前流程&#xff0c;才能往下个流程去。 而异步&#xff0c;则是启动当前流程以后&#xff0c;不需要等待流程完成&#xff0c;立刻就去执行下一个流程。 同步示例 创建一个窗体&#xff0c;往窗体里…

Mybatis进阶2

Mybatis进阶1-CSDN博客 Mybatis入门-CSDN博客 Mybatis入门2-CSDN博客 我们接下来要学习Mybatis的高级查询 我们先在数据库中准备我们需要的数据表 teacher表 课程表&#xff1a;与教师表是一对多的关系&#xff0c;所以有一个外键字段 学生表 由于学生表和课程表是多对多的…

翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习四

合集 ChatGPT 通过图形化的方式来理解 Transformer 架构 翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习一翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深度学习二翻译: 什么是ChatGPT 通过图形化的方式来理解 Transformer 架构 深…

支付宝支付流程

第一步前端&#xff1a;点击去结算&#xff0c;前端将商品的信息传递给后端&#xff0c;后端返回一个商品的订单号给到前端&#xff0c;前端将商品的订单号进行存储。 对应的前端代码&#xff1a;然后再跳转到支付页面 // 第一步 点击去结算 然后生成一个订单号 // 将选中的商…