排序-java(插入排序和选择排序)

news2024/11/29 0:46:38

一,分类

主要的排序大致分为以下几类:

1,插入排序,又分为直接插入排序和希尔排序

2,选择排序,又分为选择排序和堆排序

3,交换排序,又分为冒泡排序和快速排序

4,归并排序

二,插入排序

1,直接插入排序

一个数组,定义两个变量i和j,i从数组的第二个元素开始往后遍历,直到数组结束。每次遍历把下标为i的值储存到临时变量tmp中。与此同时,j=i-1,j往前遍历,每一次下标j对应的值都与tmp进行比较,如果j的对应值大于tmp,则arr【j+1】=arr【j】,如果小于tmp的值,则直接跳出循环。因为如果遇到小于tmp的值,则这个值前面的数据肯定都小于tmp,这时就可以直接将tmp的值放入arr【j+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 (tmp<array[j]){
                array[j+1]=array[j];
            }
            else {
                break;
            }
        }
        array[j+1]=tmp;
    }
}

简易图:

总结:

(1)对于直接插入排序,越有序,排序越快,所以如果一组数据趋于有序时,可以优先选择直接插入排序

(2)时间复杂度:O(n^2)

(3)空间复杂度:O(1)

(4)稳定性:稳定

注:稳定性指:

2,希尔排序

希尔排序时对直接插入排序的优化。其又称为缩小增量的排序,将数据分成不同的组,然后将每一组的数据进行直接插入排序,然后将组数不断减少,直到减少到一,每减少一次就排一次序。当组数多的时候每组的数据少,所以时间复杂度小,当组数小的时候,虽然数据比较多,但是数据是趋于有序的,所以直接插入排序的时间复杂度也较低,综上所述,这种方法的效率较高。

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

总结:

(1) 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算

时间复杂度(估算):O(n*log2(n))

(2)空间复杂度:O(1)

(3)稳定性:不稳定

三,选择排序

1,选择排序

定义i和j两个变量,i从0开始遍历整个数组,定义最小值的下标变量为minIndex,当 i 每等于一个值时,minIndex=i,j就从i+1开始向后遍历,遇到array[minIndex]>array[j],就将minIndex=j从而保证这是这次 j 遍历的数据中的最小值,直到 j 遍历完整个数组后,将下标为i的值与下标为minIndex的值进行交换。从而使i的位置是这次 j 遍历的数据中的最小值。然后i++,继续寻找第二小的值放到 i 的位置……

下图为i=0时的一次遍历:

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

当然我们也可以在  j  遍历的时候同时找到最小值和最大值的下标,但需要注意的是,第一次遍历之后就可以筛选出最大值和最小值,这时最小值放第一个,最大值放最后一个,第二次遍历的时候就不需要遍历头和尾了。因此每次遍历就可以挑出一对数据,最大值和最小值。所以下一次遍历就只需要从中间寻找最大值和最小值了,所以i只需要遍历一半的数据就可以完成整个排序。

public static void selectSort2(int[]array){
    for (int i = 0; i < array.length/2; i++) {
        int minIndex= i;
        int maxIndex= i;
        for (int j = i+1; j < array.length-i; j++) {
            if (array[j]< array[minIndex]){
                minIndex=j;
            }
            if (array[j]> array[maxIndex]){
                maxIndex=j;
            }
        }
        swap(array,minIndex,i);
        if (maxIndex==0){
            maxIndex=minIndex;
        }
        swap(array,maxIndex,array.length-1-i);
    }
}

总结:

(1) 时间复杂度:O(n^2)

(2)空间复杂度:O(1)

(3)稳定性:不稳定

2,堆排序

堆排序时首先要调整成大根堆,因为大根堆下标为0的元素一定是最大的,所以可以将第一个元素和最后一个下标的元素交换,然后将第一个元素向下调整重新调整为大根堆,调整的终点是前一次调整的数组长度-1(已经选出了最大的元素,现在需要在剩余的元素中找到第二大的,所以向下调整大范围不包括已经排好序的数据),然后然后循环上述行为。使数组中的每一个元素都得到调整从而就可以得到顺序了。

延伸说明:

调整大根堆:我们需要求出最后一个子节点的父节点,然后向前遍历,将每一个父节点就进行向下调整。

向下调整:需要知道需要调整的父节点的下标和调整的范围(如果是建立大根堆,调整的范围就是到最后一个下标),知道父亲节点后求出左子节点,然后判断是否有右子节点,如果有那么判断array[child+1]与array[child]的大小关系,如果关系是大于,那么child++,这样保证child所指向的是较大的子孩子。然后将较大的子孩子和父节点的值进行比较,如果孩子节点大于父亲节点,那么两者交换,因为如果两者交换的话,会影响被交换为子节点的节点作为父亲节点时,与它自己的子节点的大小关系,所以交换后要parent=child; child=parent*2+1;然后再次重复循环上述操作,直到孩子节点是越界,则代表调整完毕。但如果父亲节点大于孩子节点就可以直接跳出循环了,因为父子节点之间不需要交换,而子节点以下的节点本身就是调整好的所以不需要再次调整,直接跳出循环即可。

public static void siftDown(int []array,int parent,int end){
    int child=parent*2+1;
    while (child<end+1){
        if (child+1<=end){
            if (array[child+1]>array[child]){
                child++;
            }
        }
        if (array[child]>array[parent]){
            swap(array,child,parent);
            parent=child;
            child=parent*2+1;
        }else {
            break;
        }

    }


}
public static void createBigHeap(int[]array){
    int child=array.length-1;
    int parent= (child-1)/2;
    while (parent>=0){
        siftDown(array,parent,array.length-1);
        parent--;
    }
}

public static void heapSort(int []array){
    //调整为大根堆
    createBigHeap(array);
    int end= array.length-1;
    while (end>0){
        swap(array,0,end);
        end--;
        siftDown(array,0,end);

    }
}

总结:

(1) 时间复杂度:O(n*log2(n))

(2)空间复杂度:O(1)

(3)稳定性:不稳定

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

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

相关文章

Fast R-CNN(论文阅读)

论文名&#xff1a;Fast R-CNN 论文作者&#xff1a;Ross Girshick 期刊/会议名&#xff1a;ICCV 2015 发表时间&#xff1a;2015-9 ​论文地址&#xff1a;https://arxiv.org/pdf/1504.08083 源码&#xff1a;https://github.com/rbgirshick/fast-rcnn 摘要 这篇论文提出了一…

YOLOv8_pose数据集可视化[关键点检测实践篇]

先贴代码,周末再补充解析。 这个篇章主要是对标注好的标签进行可视化,虽然比较简单,但是可以从可视化代码中学习到YOLOv8是如何对标签进行解析的。 import cv2 import numpy as np import os import randomdef read_pose_labels(label_file_path):with open(label_file_path…

MySQL的count()方法慢

前言 mysql用count方法查全表数据&#xff0c;在不同的存储引擎里实现不同&#xff0c;myisam有专门字段记录全表的行数&#xff0c;直接读这个字段就好了。而innodb则需要一行行去算。 比如说&#xff0c;你有一张短信表(sms)&#xff0c;里面放了各种需要发送的短信信息。 …

一.2.(1)双极型晶体三极管的结构、工作原理、特性曲线及主要参数

1.双极型晶体三极管的结构 学会区分P管和N管&#xff0c;会绘制符号 2.工作原理 无论是PNP 还是NPN&#xff0c;本质上放大时&#xff0c;都是发射结正偏&#xff0c;集电极反偏。&#xff08;可以简单理解为pn为二极管&#xff0c;每个三极管都有两个二极管&#xff09; 其中电…

commonjs、module 模块同时启动

怎样同时在一个项目中同时启动node服务和我们前端项目&#xff08;commonjs、module 模块同时启动&#xff09; 今天在使用node实现完增删改查的接口之后&#xff0c;将自己node代码嵌入到我们react项目中 启动完前端项目之后&#xff0c;当我使用node service.js的时候&#x…

【JavaWeb程序设计】JSP实现购物车功能

目录 一、结合之前所学的相关技术&#xff0c;编写代码实现以下购物车功能 1. 我实现的功能运行截图如下 &#xff08;1&#xff09;商品列表页面home.jsp &#xff08;2&#xff09;登录账号页面/未登录点击结账页面 &#xff08;3&#xff09;重新登录页面&#xff08;记…

STM32-PWR和WDG看门狗

本内容基于江协科技STM32视频学习之后整理而得。 文章目录 1. PWR1.1 PWR简介1.2 电源框图1.3 上电复位和掉电复位1.4 可编程电压监测器1.5 低功耗模式1.6 模式选择1.7 睡眠模式1.8 停止模式1.9 待机模式1.10 库函数 2. WDG看门狗2.1 WDG简介2.2 IWDG框图2.3 IWDG键寄存器2.4 …

如何搭建Ubuntu环境安装禅道

一、禅道安装部署的环境要求 禅道安装部署环境推荐使用 Linux Apache PHP7.0以上版本 MySQL5.5以上版本/MariaDB的组合。Nginx其次&#xff0c;不推荐IIS PHP组合。禅道需要使用PHP的这些扩展&#xff1a;pdo、pdo_mysql、json、filte、openssl、mbstring、zlib、curl、gd、…

Qt源码解析之QObject

省去大部分virtual和public方法后&#xff0c;Qobject主要剩下以下成员&#xff1a; //qobject.h class Q_CORE_EXPORT Qobject{Q_OBJECTQ_PROPERTY(QString objectName READ objectName WRITE setObjectName NOTIFY objectNameChanged)Q_DECLARE_PRIVATE(QObject) public:Q_I…

数据埋点从入门到了解

想讲讲为什么有埋点&#xff0c;举个例子 目录 什么是埋点&#xff1f;用途小红书上 埋点的主要类型代码示例1. 代码埋点前端埋点后端埋点 (Node.js 示例) 2. 全埋点示例3. 可视化埋点示例 解释常见问题埋点管理系统结论 王五是一名数据分析师&#xff0c;负责分析公司产品的用…

非NI GPIB卡与LabVIEW兼容性分析

在许多测试和测量应用中&#xff0c;通用接口总线&#xff08;GPIB&#xff09;是一种广泛使用的标准。尽管国家仪器公司&#xff08;NI&#xff09;提供的GPIB硬件和LabVIEW软件的组合被广泛接受和使用&#xff0c;但成本可能较高。因此&#xff0c;一些用户会考虑使用其他厂商…

什么是T0策略?有没有可以持仓自动做T的策略软件?

​​行情低迷&#xff0c;持仓被套&#xff0c;不想被动等待&#xff1f;长期持股&#xff0c;想要增厚持仓收益&#xff1f;有没有可以自动做T的工具或者策略&#xff1f;日内T0交易&#xff0c;做到降低持仓成本&#xff0c;优化收益预期。 什么是T0策略&#xff1f; 可以提…

Android最近任务显示的图片

Android最近任务显示的图片 1、TaskSnapshot截图1.1 snapshotTask1.2 drawAppThemeSnapshot 2、导航栏显示问题3、Recentan按键进入最近任务 1、TaskSnapshot截图 frameworks/base/services/core/java/com/android/server/wm/TaskSnapshotController.java frameworks/base/cor…

c++ primer plus 第15章友,异常和其他: 15.2.1 嵌套类和访问权限系

c primer plus 第15章友&#xff0c;异常和其他&#xff1a; 15.2.1 嵌套类和访问权限系 提示&#xff1a;这里可以添加系列文章的所有文章的目录&#xff0c;目录需要自己手动添加 例如&#xff1a;c primer plus 第15章友&#xff0c;异常和其他&#xff1a; 15.2.1 嵌套类和…

详解Amivest 流动性比率

详解Amivest 流动性比率 Claude-3.5-Sonnet Poe Amivest流动性比率是一个衡量证券市场流动性的重要指标。这个比率主要用于评估在不对价格造成重大影响的情况下,市场能够吸收多少交易量。以下是对Amivest流动性比率的详细解释: 定义: Amivest流动性比率是交易额与绝对收益率的…

柯桥职场英语学习商务英语口语生活英语培训生活口语学习

辣妹用英语怎么说&#xff1f; 辣妹在英语中通常被翻译为“hot girl”或“spicy girl”&#xff0c;但更常见和直接的是“hot chick”或简单地使用“hot”来形容。 举个例子: Shes a real hot girl with her trendy outfit and confident attitude. 她真是个辣妹&#xff0…

Linux:进程终止和进程替换

Linux&#xff1a;Linux&#xff1a;进程终止和进程替换 一、进程终止1.1 进程退出场景和创建退出方式 1.2 exit 和 _exit区别二、进程程序替换2.1 进程替换函数2.2 函数解释及命名解释函数解释命名解释 2.3 单进程程序替换&#xff08;无子进程&#xff09;2.3.1 带l函数进程替…

Ubuntu配置GitHub(第一次clone/push)

文章目录 1. 安装Git&检查连接2. 注册GitHub3. 生成&GitHub添加SSH3.1. 检查&删除已有id_rsa3.2. 生成SSH3.3. GitHub添加id_rsa.pub SSH3.4. 检查SSH 4. 继续开发可以参考参考 1. 安装Git&检查连接 安装 sudo apt-get install git检查SSH连接 ssh -T gitgi…

C++——stack和queue类用法指南

一、stack的介绍和使用 1.1 stack的介绍 1、stack是一种容器适配器&#xff0c;专门用在具有后进先出操作的上下文环境中&#xff0c;其删除只能从容器的一端进行插入与提取操作 2、stack是作为容器适配器被实现的&#xff0c;容器适配器即是对特定类封装作为其底层的容器&am…

clickhouse高可用可拓展部署

clickhouse高可用&可拓展部署 1.部署架构 1.1高可用架构 1.2硬件资源 部署服务 节点名称 节点ip 核数 内存 磁盘 zookeeper zk-01 / 4c 8G 100G zk-02 / 4c 8G 100G zk-03 / 4c 8G 100G clikehouse ck-01 / 32c 128G 2T ck-02 / 32c 128G 2T ck-03 / 32c 128G 2T ck-04 /…