简单的排序算法

news2024/11/26 22:52:38

目录

1.直接插入排序

2.希尔排序

3.选择排序

4.冒泡排序

5.计数排序

6.排序总结


1.直接插入排序

(1)思想

所谓插入排序,就是将待排序数据插入到已经有序的数据中,为了使插入后数据依然有序,就要选中一个合理的位置进行插入。

(1)定义变量i,遍历待排序数据,定义遍历j,遍历已有序数据。

(2)把i指向的值存入临时遍历tmp中,遍历有序数据

(3)如果j指向的值>tmp,让j位置元素向后移动,j--;否则不移动,结束循环 

图示展示思想:

第一步: 

第二步:比较,交换数据 

第二轮:

不断类推,直到有序(i走到非法位置)

(2)代码

代码需要完整,则要判断数组是否合法有数据等等,下面不做补充

public static void insertSort(int[] array) {
        if(array == null) {
            return;
        }
        if(array.length <= 1) {
            return;
        }
        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;//放回元素
        }
    }

前面就是为给tmp找一个合理的位置,如果j<tmp,则可以提前结束循环;否则需要走完j

(3)总结

1.时间复杂度:O(N^2)。

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

3.稳定性:稳定。

4.适应对象:元素越有序,效率越高

2.希尔排序

希尔排序就是一种特殊的直接插入排序(在它的基础上进行优化操作),比直接插入排序1效率更高。

(1)思想

1.将数据分组,每组分别进行插入排序(作为一轮)。

2.进行第二轮,缩小组距(分组后数据增加),继续进行插入排序。

3.最后一轮时,就是对原始数据进行插入排序(此时数据已经趋于有序)。

如何分组:定义一个变量gap,称为组距。也就是每间隔五个数据就有一个数据是这个组的。

 分组的间距从大到小,一开始,我们先赋值为数组的长度。下面代码的写法可以保证gap最后一次为1,完成最后的插入排序

public static void shellSort(int[] array) {
        int gap = array.length;
        while(gap > 1) {
            gap /= 2;
            shell(array,gap);//进行插入排序
        }

    }

分组后,在组内进行插入排序即可。

如何确定:无序数据和有序数据

得出插入排序部分代码:

 j每次移动的距离就是gap,保证在同组内移动。j循环结束代表一组的插入排序完成,进入下一轮(也就是下一组);

 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;
        }
    }

进入下一组:

(2)完整代码

 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 {
                    break;
                }
            }
            array[j+gap] = tmp;
        }
    }

(3)总结

1.是对直接插入排序的优化

2.时间复杂度不好计算,暂时按:O(n^1.25)-O(1.6*n^1.25)计算

3.稳定性:不稳定

3.选择排序

选择排序思想比较简单,但是时间效率很低。每轮遍历完整个数组,找到本轮最小的放到前面;第二轮再继续遍历找到当前最小的数据再放入前面。

(1)思想

定义变量:i、j

和插入排序一样定义两个变量,但是作用不同。变量i负责遍历有序数据,而变量j遍历无序数据,负责找出当前最小元素的下标(或值)。

思路图:

根据上面的思路,可以得出下面的代码

(2)完整代码

 public static void selectSort(int[] array) {

        for (int i = 0; i < array.length-1; i++) {
            int minIndex = i;//记录当前下标
            int j = i+1;
            for(;j < array.length;j++) {
                if(array[j]<array[minIndex]) {
                    minIndex = j;//最小值下标更新
                }
            }
            swap(array,i,minIndex);
        }

    }
    public static void swap(int[] array,int i,int j) {
        int tmp = array[i];
        array[i] = array[j];
        array[j] = tmp;
    }

思想和代码都比较简单,就不再做简述

(3)总结

1.效率很低,实际中少用

2.时间复杂度:O(N^2) 

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

4.稳定性:不稳定  

4.冒泡排序

冒泡排序核心,每一轮冒泡会将当前最大的元素放到最后面。每次两个数据比较,大的数据往后走。

(1)思路

待排序数组:

int[] arr = {10,9,8,7,6,5,4,3,2,1};

第一轮冒泡: 

 第二轮冒泡:

后续同理

(2)完整代码

public static void  bubbleSort(int[] array) {

        for (int i = 0; i < array.length-1; i++) {
            for (int j = 0; j < array.length-i-1; j++) {
                if(array[j] > array[j+1]) {
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
        }
    }

为了应对逆序的代码,可以做出以下优化

public static void  bubbleSort(int[] array) {

        for (int i = 0; i < array.length-1; i++) {
            boolean bool = true;
            for (int j = 0; j < array.length-i-1; j++) {
                if(array[j] > array[j+1]) {
                    bool = false;
                    int tmp = array[j];
                    array[j] = array[j+1];
                    array[j+1] = tmp;
                }
            }
            if(bool) {
                break;
            }
        }
    }

如果一轮比较下来,都没有发生交换,说明已经排好序了

(3)总结

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

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

3.稳定性:稳定  

5.计数排序

适用场景(局限性):数据基本趋于一个区间内,如:待排序数据的值都是处于0-10的范围内

(1)思路步骤

第一步:求这组数据的最大值和最小值。

第二步:创建一个计数数组,大小为这批数据的差值。

第三步:遍历原数组数组,将值作计数数组的下标,该位置++。

第四步:取出计数数组,存入原数组中

(2)完整代码

public static void countSort(int[] array) {
        //1.求最值
        int max = array[0];
        int min = array[0];
        for (int i = 1; i < array.length; i++) {
            if(array[i] > max) {
                max = array[i];
            }
            if(array[i] < min) {
                min = array[i];
            }
        }
        //2.创建计数数组并初始化
        int[] count = new int[max-min+1];
        //3.遍历数组
        for (int i = 0; i < array.length; i++) {
            int index = array[i];
            count[index-min]++;
        }
        //4.取出计数数组
        int k = 0;
        for (int i = 0; i < count.length; i++) {
            int len = count[i];

           while (len != 0) {
               array[k] = i+min;
               k++;
               len--;
           }
        }
    }

(3)总结

(1)局限性较大,空间换取时间

(2)时间复杂度:O(范围+n)

(3)空间复杂度:O(范围)

(4)稳定性:可以稳定

6.排序总结

排序方法最好时间最坏时间空间稳定性
插入排序O(n)O(n^2)O(1)稳定
希尔排序O(n)O(n^2)O(1)不稳定
选择排序O(n^2)O(n^2)O(1)不稳定
堆排序O(n*logn)O(nlogn)O(1)不稳定
冒泡排序O(n)O(n^2)O(1)稳定
快速排序O(n*logn)O(n*logn)O(logn)-O(n)不稳定
归并排序O(n*logn)O(n*logn)O(n)稳定

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

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

相关文章

易腐产品的多车厢电动车路径问题(2023)

Multi-Compartment Electric Vehicle Routing Problem for Perishable Products ABSTRACT 该研究首先提出了一个异质车队、多车室的易腐产品电动汽车路由问题&#xff08;MCEVRP-PP&#xff09;。我们捕捉到MCEVRP-PP的许多实际需求和限制&#xff0c;如多个温度区、硬时间窗…

Yolov8有效涨点,添加多种注意力机制,修改损失函数提高目标检测准确率

目录 简介 CBAM注意力机制原理及代码实现 原理 代码实现 GAM注意力机制 原理 代码实现 修改损失函数 YAML文件 完整代码 &#x1f680;&#x1f680;&#x1f680;订阅专栏&#xff0c;更新及时查看不迷路&#x1f680;&#x1f680;&#x1f680; http://t.csdnimg.c…

Claude 3 Sonnet 模型现已在亚马逊云科技的 Amazon Bedrock 正式可用!

今天&#xff0c;我们宣布一个激动人心的里程碑&#xff1a;Anthropic 的 Claude 3 Sonnet 模型现已在亚马逊云科技的 Amazon Bedrock 正式可用。 下一代 Claude (Claude 3) 的三个模型 Claude 3 Opus、Claude 3 Sonnet 和 Claude 3 Haiku 将陆续登陆 Amazon Bedrock。Amazon …

AIGC——Layer Diffusion使用潜在透明度的透明图像层扩散

前言 ControlNet的作者Lvmin Zhang大佬在新的一年又发布了新的工作LayerDiffusion&#xff0c;这个工作再次让人眼前一亮&#xff0c;和ControlNet一样&#xff0c;LayerDiffusion也是解决文生图中比较实际的问题&#xff0c;那就是生成透明的4通道RGBA图像&#xff0c;而且效…

在Mac上安装nginx+rtmp 本地服务器

需要使用终端命令&#xff0c;如果没有Homebrew&#xff0c;要安装Homebrew,执行&#xff1a; ruby -e "$(curl -fsSL https://raw.githubusercontent.com/Homebrew/install/master/install)" 一、安装Nginx 1、先clone Nginx项目到本地&#xff1a; brew tap de…

目标检测5:采用yolov8, RK3568上推理实时视频流

上一个效果图&#xff0c;海康球机对着电脑屏幕拍&#xff0c;清晰度不好。 RK3568接取RTSP视频流&#xff0c;通过解码&#xff0c;推理&#xff0c;编码&#xff0c;最终并把结果推出RTSP视频流。 数据集采用coco的80个种类集&#xff0c;通过从yovo8.pt&#xff0c;转换成R…

在 Flutter 中使用 flutter_gen 简化图像资产管理

你是否厌倦了在 Flutter 项目中手动管理图像资产的繁琐任务&#xff1f; 告别手工输入资源路径的痛苦&#xff0c;欢迎使用“Flutter Gen”高效资源管理的时代。在本文中&#xff0c;我将带您从手动处理图像资源的挫折到动态生成它们的便利。 选择1&#xff1a;痛苦手动添加–…

网络编程(3/4)

广播 ​ #include<myhead.h>int main(int argc, const char *argv[]) {//1、创建套接字int sfd socket(AF_INET, SOCK_DGRAM, 0);if(sfd -1){perror("socket error");return -1;}//2、将套接字设置成允许广播int broadcast 1;if(setsockopt(sfd, SOL_SOC…

基于FastAPI构造一个AI模型部署应用

前言 fastapi是目前一个比较流行的python web框架&#xff0c;在大模型日益流行的今天&#xff0c;其云端部署和应用大多数都是基于fastapi框架。所以掌握和理解fastapi框架基本代码和用法尤显重要。 需要注意的是&#xff0c;fastapi主要是通过app对象提供了web服务端的实现代…

SINAMICS V90 PN 指导手册 第7章 回参考点功能

如果伺服是增量式编码器&#xff0c;共有三种回参考点模式&#xff0c;分别是 通过数字量输入信号REF设置回参考点通过外部参考挡块和编码器零脉冲回参考点仅通过编码器零脉冲回参考点 如果伺服是绝对值编码器&#xff0c;除了这三种以外&#xff0c;还可以通过“ABS”调整绝…

利用 Redis 和 Lua 实现高效的限流功能

简介 在现代系统中&#xff0c;限流是一种重要的机制&#xff0c;用于控制服务端的流量并保护系统免受恶意攻击或请求泛滥的影响。本文将介绍如何利用 Redis 和 Lua 结合实现高效的限流功能。 一、什么是限流 限流指的是对系统中的请求进行控制和调节&#xff0c;确保系统在…

Nginx 可视化管理软件 Nginx Proxy Manager

一、简介 Nginx Proxy Manager 是一款开源的 Nginx 可视化管理界面&#xff0c;基于 Nginx 具有漂亮干净的 Web UI 界面。他允许用户通过浏览器界面轻松地管理和监控 Nginx 服务器&#xff0c;可以获得受信任的 SSL 证书&#xff0c;并通过单独的配置、自定义和入侵保护来管理…

ARM单片机中程序在ROM空间和RAM空间的分布(分散加载文件,Scatter-Loading Description File)

对于 K e i l u V i s i o n I D E Keil\quad uVision\quad IDE KeiluVisionIDE&#xff0c;程序编译好之后&#xff0c;代码的下载位置&#xff08; R O M ROM ROM空间&#xff09;以及代码运行的时候使用的 R A M RAM RAM空间&#xff08; R A M RAM RAM空间&#xff09;默认…

第二证券|重大转变!全球资金正重回中国股市!

外资巨头最新发声。 摩根士丹利在最新发布的陈述中称&#xff0c;全球资金正在重返我国股市。跟着部分基金对我国商场的看跌心情有所平缓&#xff0c;全球长时间出资者撤出我国股票商场&#xff08;A股和港股&#xff09;的举动现已按下暂停键。 按下暂停键或许是一个前期痕迹…

leetcode刷题(javaScript)——二叉树、平衡二叉树相关场景题总结

二叉树的知识点很多&#xff0c;在算法刷题中需要有想象力的数据结构了。主要是用链表存储&#xff0c;没有数组更容易理解。在刷二叉树相关算法时&#xff0c;需要注意以下几点&#xff1a; 掌握二叉树的基本概念&#xff1a;了解二叉树的基本概念&#xff0c;包括二叉树的定义…

pytorch什么是梯度

目录 1.导数、偏微分、梯度1.1 导数1.2 偏微分1.3 梯度 2. 通过梯度求极小值3. learning rate 1.导数、偏微分、梯度 1.1 导数 对于yx 2 2 2 的导数&#xff0c;描述了y随x值变化的一个变化趋势&#xff0c;导数是个标量反应的是变化的程度&#xff0c;标量的长度反应变化率的…

next/future/image图片根据外部容器100%填充

官网文档地址&#xff1a; https://nextjs.org/docs/pages/api-reference/components/image 主要需要使用属性fill。外部元素需要设置好position:relative <Imagexsrc"/images/1.jpg"fillsizes100vw />

浅谈块存储、文件存储、对象存储

**块存储、文件存储和对象存储各自有其独特的特点和适用场景**。具体来说&#xff1a; 1. **块存储**&#xff1a; - 描述&#xff1a;块存储将存储空间分割成固定大小的块&#xff0c;这些块可以直接映射到主机操作系统。它提供的是原始的存储空间&#xff0c;不带文件系统…

hive实战项目:旅游集市数仓建设

旅游集市数仓建设 文章目录 旅游集市数仓建设为什么要设计数据分层&#xff1f;分层设计ODS&#xff08;Operational Data Store&#xff09;&#xff1a;数据运营层DW&#xff08;Data Warehouse&#xff09;&#xff1a;数据仓库层DWD&#xff08;Data Warehouse Detail&…

软考63-上午题-【面向对象技术】-面向对象的基本概念2

一、动态绑定、静态绑定 1-1、动态绑定、静态绑定的定义 编译时进行的绑定 静态绑定 运行时进行的绑定 动态绑定 动态绑定&#xff0c;和类的继承和多态想关联的。 在运行过程中&#xff0c;当一个对象发送消息请求服务时&#xff0c;要根据接受对象的具体情况将请求的操作…