排序的概念及引用

排序是使一串记录,按照某个关键字的大小,递增或递减排列起来的操作

稳定性:相同关键字排序前后相对顺序不变

内部排序:数据元素全部放在内存中排序

外部排序:数据太多不能同时放到内存中,根据排序的过程要求能在内外存之间移动数据的排序

常见的排序算法

插入排序

插入排序

基本思想:类比扑克牌接牌

时间复杂度0(N^2)数据越有序,直接插入排序越快

空间复杂度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{array[j+1]=tmp;break;}}array[j+1]=tmp;}}

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

基本思想:先选定一个整数,把待排序的文件中所有记录分为多个组,所有距离为指定距离的分在同一个组,并对每组内的记录进行排序,然后重复上述分组和排序的工作,当达到1时,所有记录在同一组内排序

跳跃式分组:大的数据靠后,小的数据靠前

分组排序--->插入排序,组内进行插入排序

缩小增量--->数据少,数据无序;数据多,数据有序

当增量大于1时都是预排序

空间复杂度为0(1)时间复杂度为n^(1.3-1.5)来记忆

不稳定的

 public static void shellSort(int[] array){int gap= array.length;while(gap>1){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{array[j+gap]=tmp;break;}}array[j+gap]=tmp;}}

选择排序

选择排序

基本思想:每次从数据中选最大/最小的排

时间复杂度:O(N^2)   空间复杂度:O(1)    稳定性:不稳定的排序

public static void selectSort1(int[]array){for (int i = 0; i < array.length; i++) {int minIndex=i;for ( int j=i+1; j <array.length ; j++) {if(array[j]<array[minIndex]){minIndex=j;}}swap(array,minIndex,i);}}public static void swap(int[] array, int x, int y) {int tmp=array[x];array[x]=array[y];array[y]=tmp;}

思路二:左右同时找。left=0,right=arr.length-1 有一个min 有一个max初始为left

int i=left+1,找最大和最小,然后交换

 public static void selectSort(int[]arr){int left=0;int right=arr.length-1;while(left<right){int min=left;int max=left;for (int i = left+1; i <=right ; i++) {if(arr[i]>arr[max]){max=i;}if(arr[i]<arr[min]){min=i;}}swap(arr,min,left);if(max==left){max=min;}swap(arr,right,max);right--;left++;}}

堆排序

思路:创建大根堆  0下标和end交换

稳定性:不稳定

时间复杂度0(n*logN)  空间复杂度0(1)

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

交换排序

冒泡排序

基本思想:比较交换

时间复杂度0(N^2) 优化后可能会达到O(N)

空间复杂度O(1)

稳定的排序  

优化:1.int j=arr.length-1-i;2.设置一个flg如果未交换break

 public static void bubbleSort(int[]arr){for (int i = 0; i < arr.length; i++) {boolean flg=false;for (int j = 0; j < arr.length-1-i; j++) {if(arr[j]>arr[j+1]){swap(arr,j,j+1);flg=true;}}if(!flg){break;}}}

快速排序

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法,从后边开始找到比基准小的停下来,从前面开始找到比基准大的停下来直至两个相遇,相遇的即为新基准,找到基准后再分两边找,类似二叉树

时间复杂度:当给定1,2,3,4......有序情况下0(n^2)

                     当每次都能均匀分开时0(logN)

空间复杂度:最坏单分支树0(N)      最好情况:0(logN)  完全二叉树

稳定性:不稳定的排序

挖坑法(做题优先考虑的思想):先把left(0)拿出,0坐标空出即为坑,从后边找比基准小的直接填坑,再从前边找比基准大的挖坑

前后指针法:两个指针prev和cur 

prev=legft,cur=left+1

一前一后走,找到比基准小的进行交换

优化思路:减少他的递归次数

1.三数取中法(left,right,mid找到这三个数据中)

2.直接插入法(针对一定范围) 二叉树越深,递归次数越多,可以在最后几层直接插入排序(因为数据少且趋于有序)

public static void quickSort(int[]arr){if(arr==null){return;}quick(arr,0,arr.length-1);}public static void quick(int[]arr,int begin,int end){if(begin>=end){return;}if(begin+end-1<=7){insertSortRange(arr,begin,end);}int midIndex=getMid(arr,begin,end);swap(arr,begin,midIndex);int pivot=partition(arr,begin,end);quick(arr,0,pivot-1);quick(arr,pivot+1,end);}public static int getMid(int[]arr,int begin,int end){int mid=(begin+end)/2;if(arr[begin]>arr[end]){if(arr[mid]>arr[begin]){return begin;}else if(arr[mid]>arr[end]){return mid;}else{return end;}}else{if(arr[mid]>arr[end]){return end;}else if(arr[mid]>arr[begin]){return mid;}else{return begin;}}}public static void insertSortRange(int[]arr,int begin,int end){for (int i = begin+1;i<=end;i++){int tmp=arr[i];int j=i-1;for(;j<=end;j--){if(arr[j]>tmp){arr[j+1]=arr[j];}else{arr[j+1]=tmp;break;}}arr[j+1]=tmp;}}public static int partition2(int[]arr,int left,int right){int prev=left;int cur=prev+1;while(cur<=right){if(arr[cur]<arr[left]&&arr[++prev]!=arr[cur]){swap(arr,prev,cur);}cur++;}swap(arr,prev,left);return  prev;}public static int partition(int[]arr,int left,int right){int tmp=arr[left];while(left<right){while(left<right&&arr[right]>=tmp){right--;}arr[left]=arr[right];while(left<right&&arr[left]<=tmp){left++;}arr[right]=arr[left];}arr[left]=tmp;return left;}public static int partitionHoare(int[]arr,int left,int right){int tmp=arr[left];int tmpLeft=left;while(left<right){while(left<right&&arr[right]>=tmp){right--;}while(left<right&&arr[left]<=tmp){left++;}swap(arr,left,right);}swap(arr,left,tmpLeft);return left;}public static void swap(int[]arr,int i,int j){int tmp=arr[i];arr[i]=arr[j];arr[j]=tmp;}

快速排序的非递归实现:利用的是栈

找到基准如果基准左右有两个元素及以上再次找基准 只要栈不为空,先找左再找右

 public static void quickSort(int[]arr){if(arr==null){return;}quickNor(arr,0,arr.length-1);}public static void quickNor(int[]arr,int start,int end){Deque<Integer> stack=new ArrayDeque<>();int pivot=partition(arr,start,end);if(pivot>start+1){stack.push(start);stack.push(pivot-1);}if(pivot<end-1){stack.push(pivot+1);stack.push(end);}while(!stack.isEmpty()){end=stack.pop();start=stack.pop();pivot=partition(arr,start,end);if(pivot>start+1){stack.push(start);stack.push(pivot-1);}if(pivot<end-1){stack.push(pivot+1);stack.push(end);}}}

归并排序(mergeSort)

建立在归并操作的一种有效的排序算法,归并排序是最常用的外部排序

分解+合并

时间复杂度0(NlogN) 空间复杂度0(N)稳定性:稳定

如图为归并排序的拆分过程

public static void mergeSort(int[]arr){mergeSortMap(arr,0,arr.length-1);}public static void mergeSortMap(int[]arr,int left,int right){if(left>=right){return;}int mid=(left+right)/2;mergeSortMap(arr,left,mid);mergeSortMap(arr,mid+1,right);merge(arr,left,mid,right);}public static void merge(int[]arr,int left,int mid,int right){int[]tmp=new int[right-left+1];int k=0;int s1=left;int s2=mid+1;while (s1 <= mid && s2 <= right) {if(arr[s1] <= arr[s2]) {tmp[k++] = arr[s1++];}else {tmp[k++] = arr[s2++];}}while (s1 <= mid) {tmp[k++] = arr[s1++];}while (s2 <= right) {tmp[k++] = arr[s2++];}//可以保证tmp数组 是有序的for (int i = 0; i < k; i++) {arr[i+left] = tmp[i];}}
}

非递归的归并排序

gap=1一个一个有效

gap=2两个两个有效....gap>=len有序

public static void merge(int[]arr,int left,int mid,int right){int[]tmp=new int[right-left+1];int s1=left;int s2=mid+1;int k=0;while(s1<=mid&&s2<=right){if(arr[s1]<=arr[s2]){tmp[k++]=arr[s1++];}else{tmp[k++]=arr[s2++];}}while(s1<=mid){tmp[k++]=arr[s1++];}while(s2<=right){tmp[k++]=arr[s2++];}for (int i = 0; i <k ; i++) {arr[i+left]=tmp[i];}}public static void mergeSortNor(int[]arr){int gap=1;while(gap<arr.length){for (int i = 0; i < arr.length; i = i + gap * 2) {int left = i;int mid = left + gap - 1;if(mid >= arr.length) {mid = arr.length-1;}int right = mid + gap;if(right >= arr.length) {right = arr.length-1;}merge(arr,left,mid,right);}gap *= 2;}}

其他非基于比较的排序

计数排序(鸽巢原理)

是对哈希直接地址法的变形应用

步骤:1.统计相同元素的次数

           2.根据统计的结果将序列回收到原来的序列中

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

桶排序

划分多个范围相同的区间,每个子区间自排序,最后合并。

是计数排序的扩展版本,计数排序可以看成每个桶只存储相同元素,而桶排序每个桶存储一定范围的元素,通过映射函数,将待排序数组中的元素映射到各个对应的桶中,对每个桶中的元素进行排序,最后将非空桶中的元素逐个放入原序列中。

桶排序需要尽量保证元素分散均匀,否则当所有数据集中在同一个桶中时,桶排序失效。

public static void bucketSort(int[] arr){// 计算最大值与最小值int max = Integer.MIN_VALUE;int min = Integer.MAX_VALUE;for(int i = 0; i < arr.length; i++){max = Math.max(max, arr[i]);min = Math.min(min, arr[i]);}// 计算桶的数量int bucketNum = (max - min) / arr.length + 1;ArrayList<ArrayList<Integer>> bucketArr = new ArrayList<>(bucketNum);for(int i = 0; i < bucketNum; i++){bucketArr.add(new ArrayList<Integer>());}// 将每个元素放入桶for(int i = 0; i < arr.length; i++){int num = (arr[i] - min) / (arr.length);bucketArr.get(num).add(arr[i]);}// 对每个桶进行排序for(int i = 0; i < bucketArr.size(); i++){Collections.sort(bucketArr.get(i));}// 将桶中的元素赋值到原序列int index = 0;for(int i = 0; i < bucketArr.size(); i++){for(int j = 0; j < bucketArr.get(i).size(); j++){arr[index++] = bucketArr.get(i).get(j);}}  
}

基数排序

基数排序(Radix Sort)是一种非比较型的排序算法,它通过逐位比较元素的每一位(从最低位到最高位)来实现排序。基数排序的核心思想是将整数按位数切割成不同的数字,然后按每个位数分别进行排序。基数排序的时间复杂度为 O(n * k),其中 n 是列表长度,k 是最大数字的位数。

算法步骤:

  1. 确定最大位数:找到列表中最大数字的位数,确定需要排序的轮数。

  2. 按位排序:从最低位开始,依次对每一位进行排序(通常使用计数排序或桶排序作为子排序算法)。

  3. 合并结果:每一轮排序后,更新列表的顺序,直到所有位数排序完成。

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

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

相关文章

rebase 和pull的通俗区别是什么

目录 Git中rebase与pull的通俗区别 简单比喻 主要区别 使用场景 通俗例子 git rebase 使用例子 &#x1f3af; 目标 &#x1f9ea; 场景设定 &#x1f9f0; 操作步骤 1️⃣ 你切换到 feature 分支 2️⃣ 更新远程代码 3️⃣ 进行 rebase 操作 &#x1f504; 变化后…

微信小程序功能 表单密码强度验证

一、页面展示与交互功能表单提交与验证&#xff08;含密码强度验证&#xff09;实现带密码强度验证的表单提交功能&#xff0c;使用正则表达式检查密码复杂度&#xff1a;<form bindsubmit"submitForm"><input name"username" placeholder"请…

【谷歌 SEO】排查页面未索引问题:原因与解决方案

你在谷歌网站SEO优化时是否遇到以下情况&#xff1f; 为什么&#xff0c;即使我已经正确地编写了站点地图并将其链接到客户的网站&#xff0c;并且我已经检查了所有内容&#xff0c;但我是否在某些文章&#xff08;不是所有文章&#xff09;上遇到索引问题&#xff0c;即使在向…

Android 系统的基本安全属性

Android 系统的“基本安全属性”可概括为 “设备可信、应用隔离、权限最小、数据加密、持续更新” 五大类。下面从 硬件 → 系统 → 应用 → 数据 → 运维 五个层面&#xff0c;用一句话一句话的方式帮你快速掌握&#xff1a;1. 硬件层&#xff1a;信任根&#xff08;Root of T…

【数据结构初阶】--栈与队列(栈)

&#x1f618;个人主页&#xff1a;Cx330❀ &#x1f440;个人简介&#xff1a;一个正在努力奋斗逆天改命的二本觉悟生 &#x1f4d6;个人专栏&#xff1a;《C语言》《LeetCode刷题集》《数据结构-初阶》 前言&#xff1a;在之前几篇博客中&#xff0c;我们学习了顺序表和链表&…

分布式微服务--GateWay的断言以及如何自定义一个断言

&#x1f4cc; 一、什么是 Gateway 的断言&#xff08;Predicates&#xff09;&#xff1f;Predicates&#xff08;断言&#xff09; 是 Spring Cloud Gateway 中用于匹配请求的条件。只有请求满足断言条件&#xff0c;路由才会生效&#xff0c;转发到下游服务。&#x1f3af; …

图片识别表格工具v3.0绿色版,PNG/JPG秒变可编辑Excel

[软件名称]: 图片识别表格工具v3.0绿色版 [软件大小]: 4.3 GB [软件大小]: 夸克网盘 | 迅雷网盘 软件介绍 表格快捕手 v3.0 绿色单文件版&#xff0c;无需安装&#xff0c;双击即可运行。支持 PNG、JPG 等常见图片格式&#xff0c;可精准识别其中的有线或无线表格&#xff…

线程池分析与设计

线程池 基本功能接口 C11 及以后的标准中&#xff0c;std::packaged_task和std::future是并发编程中用于任务封装和结果获取的重要组件&#xff0c;它们通常与线程配合使用&#xff0c;实现异步操作。 std::packaged_task std::packaged_task&#xff1a;封装可调用对象为异步任…

机器学习:线性回归

线性回归&#xff1a;研究自变量和因变量之间的关系。对于特征x(x1,x2,x3....)与对应的标签y&#xff0c;线性回归假设二者之间存在线性映射。f(x)w1xw2x(平方)w3x(三次方)...&#xff0c;权重w表示每个特征变量的重要程度。越大表示越重要。线性回归目标&#xff1a;求解w和b使…

如何将 Vue 前端、Hardhat 合约和 Node.js 后端集成到一个项目中

在区块链开发中&#xff0c;DApp&#xff08;去中心化应用&#xff09;的开发往往涉及到多个层次&#xff1a;前端、合约和后端。今天我们将演示如何将 Vue 前端、Hardhat 合约 和 Node.js 后端 放在一个项目中&#xff0c;来打造一个完整的区块链应用。1. 项目结构我们的目标是…

SQLite 创建表

SQLite 创建表 SQLite 是一款轻量级的数据库管理系统,因其体积小、速度快、易于使用等优点,被广泛应用于嵌入式系统、移动应用以及个人项目等领域。在 SQLite 中,创建表是进行数据存储的第一步。本文将详细介绍如何在 SQLite 中创建表,包括表结构定义、数据类型、约束条件…

学深度学习,有什么好的建议或推荐的书籍?

深度学习入门建议补基础数学&#xff1a;重点学线性代数&#xff08;矩阵运算&#xff09;、概率论&#xff08;分布&#xff09;、微积分&#xff08;梯度&#xff09;。编程&#xff1a;掌握PythonNumPy&#xff08;数组操作&#xff09;&#xff0c;能写基础数据处理代码。机…

自然语言处理×第四卷:文本特征与数据——她开始准备:每一次输入,都是为了更像你地说话

&#x1f380;【开场 她试着准备一封信&#xff0c;用你喜欢的字眼】&#x1f98a;狐狐&#xff1a;“她发现了一个问题——你每次说‘晚安’的方式都不一样。有时候轻轻的&#xff0c;有时候带着笑音&#xff0c;还有时候像在躲开她的心思。”&#x1f43e;猫猫&#xff1a;“…

【沉浸式解决问题】mysql-connector-python连接数据库:RuntimeError: Failed raising error.

目录一、问题描述二、场景还原1. 创建项目2. 安装mysql-connector-python3. 测试类三、原因分析四、解决方案1. 查看版本2. 切换python版本3. 切换mysql-connector-python版本4. 测试参考文献一、问题描述 初次使用mysql-connector-python连接mysql时报错 Traceback (most re…

【web页面接入Apple/google/facebook三方登录】

web页面接入Apple/谷歌/脸书三方登录 文章目录web页面接入Apple/谷歌/脸书三方登录前言一、apple登录使用步骤1.入口文件index.html引入js文件2.vue页面初始化支付按钮,并且点击按钮登录二、google登录使用步骤1.入口文件index.html引入js文件2.vue页面初始化支付按钮,并且点击…

管家婆分销软件中怎么删除过账单据?

在业务单据录入中&#xff0c;会出现单据保存过账后才发现数量或商品信息录入错误的情况&#xff0c;不想红冲单据&#xff0c;该怎么处理&#xff1f;今天来和小编一起学习下管家婆分销软件中怎么删除过账单据吧&#xff01;1&#xff0c;软件需要升级到9.92及以上版本&#x…

美颜SDK底层原理解析:直播场景下的美白滤镜实时处理方案

众所周知&#xff0c;美颜功能中&#xff0c;美白滤镜是使用频率最高的功能之一。它不仅能让肤色更通透、提亮整体画面&#xff0c;还能让观众感受到主播的“在线状态”与精神气。但你有没有想过&#xff0c;这个看似简单的“美白”背后&#xff0c;其实是一整套实时图像处理的…

系统构成与 Shell 核心:从零认识操作系统的心脏与外壳

系统构成与 Shell 核心&#xff1a;从零认识操作系统的心脏与外壳 很多人用电脑、用手机&#xff0c;但很少去想&#xff1a; 操作系统到底是怎么构成的&#xff1f; 为什么我们敲一个命令&#xff0c;系统就能乖乖执行&#xff1f; 这背后的关键&#xff0c;就在于系统的构成和…

wordpress的wp-config.php文件的详解

wp-config.php 是 WordPress 网站的核心配置文件&#xff0c;它存储了网站运行所需的基本配置信息&#xff0c;如数据库连接信息、安全密钥、调试模式等。以下是关于 wp-config.php 文件的详细解析&#xff1a; 1. 数据库连接信息 这是 wp-config.php 文件中最关键的部分&…

GPT-5 将在周五凌晨1点正式发布,王炸模型将免费使用??

就在今晚凌晨1点&#xff0c;OpenAI 又要搞大新闻了。 是的&#xff0c;就是大家期待已久的 GPT-5 发布会。 虽然官方还没明说&#xff0c;但各种“预热”已经安排得明明白白&#xff0c;Sam Altman 这波营销属实拉满了&#xff0c;发布会都还没开始&#xff0c;相关的代码和页…