直接插入排序 希尔排序 选择排序 堆排序

目录

一. 排序的概念及应用

1.1 排序的概念

1.2 常见的排序算法

二. 常见排序算法的实现(从小到大排序)

2.1 插入排序

2.1.1基本思想:

2.1.2 直接插入排序

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

2.2 选择排序

2.2.1基本思想:

2.2.2 直接选择排序:

2.2.3 堆排序


一. 排序的概念及应用

1.1 排序的概念

排序 :所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。
稳定性 :假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j] ,且 r[i]r[j] 之前,而在排序后的序列中, r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

 

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

1.2 常见的排序算法

二. 常见排序算法的实现(从小到大排序)

2.1 插入排序

2.1.1基本思想:

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到 一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想

2.1.2 直接插入排序

当插入第 i(i>=1) 个元素时,前面的 array[0],array[1],…,array[i-1] 已经排好序,此时用 array[i] 的排序码与 array[i-1],array[i-2],…的排序码顺序进行比较,找到插入位置即将 array[i] 插入,原来位置上的元素顺序后移
思路:
  1. 从第二个元素i = 2时开始插入, 将第i个元素放在tmp中, 设j = i-1
  2. 如果小标为j的值大于tmp, 说明tmp要插在j前面, 所以arr[j+1]= arr[j], 将j所指的值向后移动, 给i让出位置,  j继续向前移动
  3.  但如果j所指的值小于tmp, 则说明j的值的位置不需要变化, 说明tmp找到了自己的位置, 直接将arr[j+1] = tmp , 因为前面的数据已经有序, 所以直接跳出循环即可, 前面的元素不用比较, 一定是小于tmp的
  4. 如果循环走完了, 即j = -1了, 说明tmp是最小的一个数据, 直接放在数组的最前面即可, 前面已经腾出了位置,即 arr[j+1] = tmp
  5.  继续循环上述步骤, 指到将数组的元素全部插入
代码:
 public static void insertSort(int[] arr){
        for (int i = 1; i <arr.length ; i++) {
            int tmp = arr[i];
            int j = i-1;
            for ( ; j >= 0; j--) {
                if(arr[j] > tmp){
                    arr[j+1] = arr[j];
                }else{
                    //arr[j+1] = tmp;
                    break;
                }
            }
            arr[j+1] = tmp;
        }
    }

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

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

希尔排序法又称缩小增量法。希尔排序法的基本思想是: 先选定一个整数gap,把待排序文件中所有记录分成多个组, 所有距离为gap的记录分在同一组内,并对每一组内的记录进行排序。然后,缩小gap的值,重复上述分组和排序的工作。当到达gap  =1 时,所有记录在统一组内排好序
思路:
  1. 首先我们要分组gap, 第一次分组, 分成数组长度的一半, 接下来分组的方式有很多, 可以gap = gap/2, 可以gap = gap/3 +1 , 等等, 现在没有任何理论可以证明哪种分组最好, 这里我们使用gap= gap/2
  2. 分组分到所有的数据为一组, 即gap = 1时,停止
  3. 每一次分组, 我们都要对组内的元素进行排序, 我们选择的方法时直接插入排序, 可参考上述
  4. 但需要注意的是, 如何找到组内的元素, 我们可以将i设成gap, 很巧妙的是, i此时正好是每个组内的第二个元素, 那么前面的元素, 即 j 就是i-gap, j的移动单位就为gap, i每次向后走1, 可以到下一个组进行排序, 当i走到数组的最后时, 每个组内的元素都是有序的
代码:
public static void shellSort(int[] arr){
        int gap = arr.length/2;
        while(gap!= 1){
            gap = gap/2;
            shell(arr, gap);
        }
    }
    private static void shell(int[] arr,int gap){
        for (int i = gap; i < arr.length; i++) {
            int tmp = arr[i];
            int j = i-gap;
            for (; j>=0; j-=gap) {
                if(arr[j] > tmp){
                    arr[j+gap] = arr[j];
                }else{
                    break;
                }
            }
            arr[j+gap] = tmp;
        }
    }
希尔排序的特性总结:
  •  希尔排序是对直接插入排序的优化。
  •  gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
  •  希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定
  •  稳定性:不稳定

2.2 选择排序

2.2.1基本思想:

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

2.2.2 直接选择排序:

在元素集合 array[i]--array[n-1] 中选择关键码最大 ( ) 的数据元素, 若它不是这组元素中的最后一个( 第一个 ) 元素,则将它与这组元素中的最后一个(第一个)元素交换在剩余的array[i]--array[n-2] array[i+1]--array[n-1] )集合中,重复上述步骤,直到集合剩余 1 个元素
思路1:
  1. 设i=0, 将i存放在minIndex里, 假设i是最小值的下标
  2. 遍历i后面的元素, 如果有比minIndex下标的值小的数据, 则更改minIndex的值, 即minIndex = j
  3. 遍历完成后, minIndex里面存放的是最小数据的值, 接着交换i和minIndex下标的值

注意: 此时不能写arr[i] = arr[minIndex], 如果这样写, 假设i下标存放的不是最小值, 那么用minIndex下标的值将i下标的值覆盖, 则会丢失i下标的值

     4. 接着i++, 循环上述步骤, 直到遍历完整个数组

代码:
public static void selectSort(int[] arr){
        for (int i = 0; i < arr.length; i++) {
            int minIndex = i;
            for (int j = i+1; j < arr.length; j++) {
                if(arr[j] < arr[minIndex]){
                    minIndex = j;
                }
            }
            swap(arr,i,minIndex);
        }
    }
    private static void swap(int[] arr,int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }

思路2:

  1. 相当于思路1的优化, 遍历一遍数组可以同时找出最小值和最大值
  2. left 和 right相当于思路1中i的作用
  3. i 相当于思路1中j的作用, 用来遍历数组(注意:此时要从left开始遍历, 而不是left+1, 因为有可能left值就是最大值, 如果从left+1开始, 则最大值找不到)
  4. minIndex 和 maxIndex作用同样是存放最小值下标和最大值下标

代码:

public static void selectSort2(int[] arr){
        int left = 0;
        int right = arr.length -1;
       while(left< right){
           for (int i = left; i <= right ; i++) {
               int minIndex = left;
               int maxIndex = right;
               if(arr[i] < arr[minIndex]){
                 minIndex = i;
               }
               if(arr[i] > arr[maxIndex]){
                  maxIndex = i;
               }
               swap(arr,left,minIndex);
               swap(arr,right,maxIndex);
               left++;
               right--;
           }
       }
    }
    private static void swap(int[] arr,int i,int j){
        int tmp = arr[i];
        arr[i] = arr[j];
        arr[j] = tmp;
    }
直接选择排序的特性总结
  •  直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用
  •  时间复杂度:O(N^2)
  •  空间复杂度:O(1)
  •  稳定性:不稳定

2.2.3 堆排序

堆排序 (Heapsort) 是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。
思路:
  1. 建立大根堆
  2. 交换堆顶元素和最后一个元素end, 这样就找到的最大的数放在最后
  3. 向下调整成大根堆, 但不算最后一个结点, 因为最后一个结点已经在应该的位置, 这样堆顶元素又变成了除最后一个元素外最大的元素
  4. 重复前两个步骤, 交换倒数第二个元素end--和堆顶元素, 这样就找到了倒数第二大的元素, 以此类推, 直到end==0时, 说明已经全部有序, 输出即可
代码:
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);
        }
    }
    private static void siftDown(int[] arr, int parent, int len){
        int child = (parent*2)+1;
        while(child < len){
            if(child +1 < len && arr[child+1]>arr[child]){
                child = child+1;
            }
            if(arr[child] > arr[parent]){
                swap(arr,child,parent);
                parent = child;
                child = (parent*2)+1;
            }else{
                break;
            }
        }
    }
【堆 排序的特性总结
  •  堆排序使用堆来选数,效率就高了很多。
  •  时间复杂度:O(N*logN)
  •  空间复杂度:O(1)
  •  稳定性:不稳定
未完待续...

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

保障校园网络安全用堡垒机的几个原因分析

校园&#xff0c;人人都熟悉的地方&#xff0c;梦想知识开始的地方。在互联网数字化快速发展的今天&#xff0c;网络安全的学习环境是非常必要的。所以采购保障校园网络安全工具是必要的。那为什么一定要用堡垒机呢&#xff1f;这里我们一起来简单分析一下原因。 保障校园网络…

iOS - Runtime-消息机制-objc_msgSend()

iOS - Runtime-消息机制-objc_msgSend() 前言 本章主要介绍消息机制-objc_msgSend的执行流程&#xff0c;分为消息发送、动态方法解析、消息转发三个阶段&#xff0c;每个阶段可以做什么。还介绍了super的本质是什么&#xff0c;如何调用的 1. objc_msgSend执行流程 OC中的…

OceanBase中NOT EXISTS是否需要被改写

作者简介 张瑞远&#xff0c;曾经从事银行、证券数仓设计、开发、优化类工作&#xff0c;现主要从事电信级IT系统及数据库的规划设计、架构设计、运维实施、运维服务、故障处理、性能优化等工作。 持有Orale OCM,MySQL OCP及国产代表数据库认证。 获得的专业技能与认证包括 Oce…

安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 从0开始 工具操作解析【三】

同类博文; 安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 工具操作解析 安卓玩机工具推荐----MTK芯片读写分区 备份分区 恢复分区 制作线刷包 工具操作解析【二】-CSDN博客 回顾以往 在以前的博文简单介绍了这款工具的rom制作全程。今天针对这款工具的…

Rust 02.控制、引用、切片Slice

1.控制流 //rust通过所有权机制来管理内存&#xff0c;编译器在编译就会根据所有权规则对内存的使用进行 //堆和栈 //编译的时候数据的类型大小是固定的&#xff0c;就是分配在栈上的 //编译的时候数据类型大小不固定&#xff0c;就是分配堆上的 fn main() {let x: i32 1;{le…

YoloV5改进策略:Neck和Head改进|ECA-Net:用于深度卷积神经网络的高效通道注意力|多种改进方法|附结构图

摘要 本文使用ECA-Net注意力机制加入到YoloV5Neck和Head中。我尝试了多种改进方法&#xff0c;并附上改进结果&#xff0c;方便大家了解改进后的效果&#xff0c;为论文改进提供思路。&#xff08;改进中。。。。&#xff09; 论文&#xff1a;《ECA-Net&#xff1a;用于深度…

Android中运动事件的处理

1.目录 目录 1.目录 2.前言 3.程序演示 4.第二种程序示例 5.扩展 2.前言 触摸屏&#xff08;TouchScreen&#xff09;和滚动球&#xff08;TrackBall&#xff09;是 Android 中除了键盘之外的主要输入设备。如果需要使用触摸屏和滚动球&#xff0c;主要可以通过使用运动事…

ruoyi-nbcio-plus基于vue3的flowable的流程条件的升级修改

更多ruoyi-nbcio功能请看演示系统 gitee源代码地址 前后端代码&#xff1a; https://gitee.com/nbacheng/ruoyi-nbcio 演示地址&#xff1a;RuoYi-Nbcio后台管理系统 http://122.227.135.243:9666/ 更多nbcio-boot功能请看演示系统 gitee源代码地址 后端代码&#xff1a…

JavaScript中的继承方式详解

Question JavaScript实现继承的方式&#xff1f; 包含原型链继承、构造函数继承、组合继承、原型式继承、寄生式继承、寄生组合式继承和ES6 类继承 JavaScript实现继承的方式 在JavaScript中&#xff0c;实现继承的方式多种多样&#xff0c;每种方式都有其优势和适用场景。以下…

HarmonyOS(鸿蒙开发)入门篇

如果需要学习鸿蒙开发可以查看以下学习资源链接 OpenAtom OpenHarmony Develop applications - HUAWEI HarmonyOS APP 转载请注明出处HarmonyOS(鸿蒙开发&#xff09;入门篇-CSDN博客&#xff0c;谢谢&#xff01;

unity 数据的可视化

【Unity 实用插件篇】| 可视化图表插件XCharts (折线图、柱状图、饼图等)详细教学-腾讯云开发者社区-腾讯云 Package https://github.com/XCharts-Team/XCharts/releases 官方文档案例 入门教程&#xff1a;5分钟上手 XCharts 3.0 | XCharts (xcharts-team.github.io)

Linux 系统基础操作命令

当前市面上常见的系统&#xff1a;Windows、Linux、Mac OS、Android、IOS…… Linux 不太适合日常使用&#xff0c;但是非常适合用于开发。因此作为一个程序猿来说&#xff0c;Linux 都是务必要掌握的。 Linux 介绍 Linux 发行版 目前市面上比较知名的发行版有&#xff1a;R…

c(RGDfK)-FITC, 绿色荧光FITC标记细胞穿膜肽c(RGDfk

中文名称 &#xff1a;荧光标记c&#xff08;RGDfk&#xff09;环肽 英 文 名 &#xff1a;c(RGDfK)-FITC c(RGDfK(FITC)) 品 牌 &#xff1a;Tanshtech 单字母&#xff1a; c(RGD-DPhe-K&#xff08;Fitc&#xff09;) 三字母&#xff1a;Cyclo(Arg-Gly-Asp…

web学习笔记(四十六)

目录 1. path 路径模块 1.1 导入path模块 1.2 path.join()路径拼接 1.3 path.basename() 获取路径中的文件名 1.4 path.extname() 获取路径中的扩展名 2.服务器的相关概念 2.1 IP 地址 2.2 域名和域名服务器 2.3 端口号 3. http 模块 3.1使用http模块搭建服务器的步…

WIFI驱动移植实验:配置 Linux 内核

一. 简介 前面文章删除了Linux内核源码&#xff08;NXP官方的kernel内核源码&#xff09;自带的 WIFI驱动。 WIFI驱动移植实验&#xff1a;删除Linux内核自带的 RTL8192CU 驱动-CSDN博客 将正点原子提供的 rtl8188EUS驱动源码添加到 kernel内核源码中。文章如下&#xff1a…

Day59-Nginx反向代理与负载均衡算法精讲及会话保持精讲

Day59-Nginx反向代理与负载均衡算法精讲及会话保持精讲 7.nginx负载均衡调度算法7.1 什么是nginx负载均衡调度算法7.2 nginx负载均衡调度算法有哪些。 8.负载均衡后端的会话保持8.1 nginx负载均衡会话(session)保持8.2 负载均衡集群会话保持8.3 实践共享会话保持 7.nginx负载均…

《Mahjong Bump》

Mahjong Bump 类型&#xff1a;Tile 三消 视角&#xff1a;2d 乐趣点&#xff1a;清空杂乱快感&#xff0c;轻松的三合一休闲 平台&#xff1a;GP 时间&#xff1a;2021 个人职责&#xff1a; 所有程序部分开发 上架 GooglePlay 相关工做 针对游戏数据做出分析&#xff0c;讨论…

并发编程之的HashSet和HashMap的详细解析

HashSet不安全 HashSet也是线程不安全的&#xff0c;底层没有进行任何线程同步处理。 在hashset的源码中&#xff0c;底层是用hashmap实现的&#xff1a; 每次add的时候&#xff0c;把值放在了map对象中的key&#xff0c;而map对象的value则全部统一放一个常量&#xff1a; 在下…

【前端学习——js篇】6.事件模型

具体见&#xff1a;https://github.com/febobo/web-interview 6.事件模型 ①事件与事件流 事件(Events) 事件是指页面中发生的交互行为&#xff0c;比如用户点击按钮、键盘输入、鼠标移动等。在js中&#xff0c;可以通过事件来触发相应的操作&#xff0c;例如执行函数、改变…

STM32H743驱动SSD1309(3)

接前一篇文章&#xff1a;STM32H743驱动SSD1309&#xff08;2&#xff09; 三、命令说明 1. 设置命令锁定&#xff08;FDh&#xff09; 此双字节命令用于锁定OLED驱动器IC&#xff0c;不接受除其自身之外的任何命令。在输入FDh 16h&#xff08;A[2]&#xff1d;1b&#xff09;…
最新文章