【数据结构】排序基本概念、插入排序、希尔排序(详解)

news2024/11/15 11:03:15

Hi~!这里是奋斗的明志,很荣幸您能阅读我的文章,诚请评论指点,欢迎欢迎 ~~
🌱🌱个人主页:奋斗的明志
🌱🌱所属专栏:数据结构、LeetCode专栏

在这里插入图片描述

📚本系列文章为个人学习笔记,在这里撰写成文一为巩固知识,二为展示我的学习过程及理解。文笔、排版拙劣,望见谅。

在这里插入图片描述

目录

  • 一、排序的概念及引用
    • 1.排序的概念
    • 2.排序在日常生活中的运用
    • 3.常见的排序算法
  • 二、插入排序
    • 1.插入排序思想
    • 2.算法步骤 + 画图演示
    • 3.动图演示
    • 4.代码展示
    • 5.总结
  • 三、希尔排序(缩小增量排序)
    • 1.希尔排序思想
    • 2.图解
    • 3.动图演示
    • 4.解析
    • 5.完整代码
  • 四、总结


一、排序的概念及引用

1.排序的概念

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

在这里插入图片描述


  • 内部排序:数据元素全部放在内存中的排序。(接触最多)
int[] array = {3,5,2,10,9,8,17};
  • 外部排序:数据元素太多不能同时放在内存中,根据排序过程的要求不能在内外存之间移动数据的排序。(使用最多的是归并排序)

2.排序在日常生活中的运用

  • 学校总分排序
    在这里插入图片描述

  • 淘宝购物排序
    在这里插入图片描述

3.常见的排序算法


在这里插入图片描述


在这里插入图片描述


二、插入排序

1.插入排序思想

直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到 一个新的有序序列 。实际中我们玩扑克牌时,就用了插入排序的思想。
它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描找到相应位置并插入。


在这里插入图片描述


2.算法步骤 + 画图演示

将待排序序列第一个元素看做一个有序序列,把第二个元素到最后一个元素当成是未排序序列。
此时 j 就是有序序列,i 以及 i 之后就是未排序序列

从头到尾依次扫描未排序序列,将扫描到的每个元素插入有序序列的适当位置。(如果待插入的元素与有序序列中的某个元素相等,则将待插入元素插入到相等元素的后面。)

在这里插入图片描述


【步骤】

  • i 从第二个开始进行比较
  • 先申请一个 tmp 的临时空间,将 i 下标对应的值放入到 tmp 中
  • j = i - 1
  • 用 j 下标对应的值进行比较
  • 当 j < 0 的时候停止

3.动图演示

明志

4.代码展示

/**
     * 使用static 静态方法 直接通过类名调用
     * 直接插入排序
     *
     * @param array
     */
    public static void insertSort(int[] array) {
        //要求数组不为空
        for (int i = 1; i < array.length; i++) {
            //将 i 下标的值放入 tmp 中
            int tmp = array[i];
            int j = i - 1;
            for (; j >= 0; j--) {
                //j下标的值和i下标的值进行比较
                if (array[j] > tmp){
                    array[j + 1] = array[j];
                }else {
//                    array[j + 1] = tmp;
                    break;
                }
            }
            array[j + 1] = tmp;
        }
    }

测试:

public class test {
    public static void main(String[] args) {
        int[] array = {3,5,2,10,9,8,17};
        Sort.insertSort(array);
        System.out.println(Arrays.toString(array));
    }
}

排序前:
在这里插入图片描述


排序后:
在这里插入图片描述


5.总结

  • 时间复杂度(数据有序的情况下)(最好):O(N)
  • 时间复杂度(数据无序的情况下)(最坏):O(N * N)
  • 空间复杂度:O(1)
  • 特点:数据越有序,直接插入排序越快
  • 稳定性:好

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

某种意义上是直接对插入排序的优化
采用分组的思想(分组怎么分,组与组之间怎么排)

1.希尔排序思想

希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成多个组, 所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达 =1时,所有记录在统一组内排好序。

2.图解


在这里插入图片描述


3.动图演示


在这里插入图片描述


4.解析

 /**
     * 希尔排序
     * 不稳定排序
     */
    public static void shellSort(int[] array){
        //首先要求出数组的长度
        int gap = array.length;
        //如何分组呢?
        //每次按照 数组的长度除以2进行分组
        while (gap > 1){
            gap /= 2;
            //调用一个方法,对已经分好的组进行 直接插入排序
            shell(array,gap);
        }
    }
  • public static void shellSort(int[] array) 方法是希尔排序的入口。
  • gap 初始化为数组的长度,表示初始的分组间隔。
  • 在每次循环中,将 gap 除以 2,直到 gap 大于 1。每次减小 gap 后,调用 shell 方法对数组进行一次分组内的插入排序。

 private static void shell(int[] array,int gap) {
        //按照10个数据元素,分成2组来进行直接插入排序
        //每组有5的元素
        for (int i = gap; i < array.length; i++) {
            //定义一个临时变量存储 将要排序的元素
            int tmp = array[i];
            int j = 0;
            for (j = i - gap; j >= 0 ; j -= gap) {
                if (array[j] > tmp){
                    array[j + gap] = array[j];
                    array[j] = tmp;
                }else {
                    break;
                }
            }
            array[j + gap] = tmp;
        }
    }
  • private static void shell(int[] array, int gap) 方法是希尔排序的辅助方法,用于对指定间隔 gap 的子数组进行插入排序。
  • gap 表示当前分组的间隔大小。
  • 外层循环从 gap 开始,依次遍历数组。
  • 在内层循环中,对每个子数组使用插入排序:将当前元素与其间隔 gap 之前的元素进行比较,如果需要,就交换它们的位置,直到找到合适的位置或者到达数组起始位置。

在 shell 方法的内部循环中,使用了类似直接插入排序的逻辑,但是相比普通的插入排序,它的插入间隔为 gap,可以加快排序的速度。

随着 gap 的逐渐减小,最后一次希尔排序中,gap 等于 1,就相当于是对整个数组进行了一次直接插入排序,最终完成整个数组的排序。

希尔排序的核心思想是通过大幅减少元素的移动次数来提高效率,尤其是对于大型数组和数据集,它比插入排序有显著的性能优势。


5.完整代码

/**
     * 希尔排序
     * 不稳定排序
     */
    public static void shellSort(int[] array){
        //首先要求出数组的长度
        int gap = array.length;
        //如何分组呢?
        //每次按照 数组的长度除以2进行分组
        while (gap > 1){
            gap /= 2;
            //调用一个方法,对已经分好的组进行 直接插入排序
            shell(array,gap);
        }
    }

    private static void shell(int[] array,int gap) {
        //按照10个数据元素,分成2组来进行直接插入排序
        //每组有5的元素
        for (int i = gap; i < array.length; i++) {
            //定义一个临时变量存储 将要排序的元素
            int tmp = array[i];
            int j = 0;
            for (j = i - gap; j >= 0 ; j -= gap) {
                if (array[j] > tmp){
                    array[j + gap] = array[j];
                    array[j] = tmp;
                }else {
                    break;
                }
            }
            array[j + gap] = tmp;
        }
    }
public static void main(String[] args) {
        int[] array = {3,5,2,10,9,8,17};
        Sort.shellSort(array);
        System.out.println(Arrays.toString(array));
    }

【排序前】:
在这里插入图片描述


【排序后】:
在这里插入图片描述


四、总结

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序当gap == 1时,数组已经接近有序的了,这样就会很 快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排 序的时间复杂度都不固定:
    《数据结构(C语言版)》— 严蔚敏
    在这里插入图片描述

《数据结构-用面向对象方法与C++描述》— 殷人昆

在这里插入图片描述

  1. 稳定性:不稳定

在这里插入图片描述

在这里插入图片描述

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

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

相关文章

java学习--泛型

前言 当我们将dog类放入集合List中想要遍历通过一下手段可实现遍历名字和年龄&#xff0c;但是当我们要加入一个新的Cat类时&#xff0c;他并不会报错&#xff0c;只有编译了才会报错&#xff0c;因为在这一步的时候注定了只能是Dog类&#xff0c;但这是非常不方便的 此时我们…

哦吼,新模型?文生图领域的新模型FLUX.1(附模型下载网盘地址和详细使用方法)

&#x1f3a1;背景 Black Forest Labs 是由 Stable Diffusion 原班人马成立的公司&#xff0c;致力于研发优质的多模态模型并开源。该公司由多位前 Stability AI 研究员组成&#xff0c;包括 Robin Rombach 在内的团队成员&#xff0c;他们在图像和视频生成领域有着杰出的贡献…

取消订单业务

文章目录 概要整体架构流程技术细节小结 概要 取消订单是电子商务、外卖平台、在线零售等多个行业中常见的业务需求之一。这项功能允许消费者或商家取消已下的订单&#xff0c;通常是因为各种原因&#xff08;如商品缺货、配送问题、支付问题等&#xff09;。 需求分析以及接…

【课程总结】day19(中):Transformer架构及注意力机制了解

前言 本章内容&#xff0c;我们将从注意力的基础概念入手&#xff0c;结合Transformer架构&#xff0c;由宏观理解其运行流程&#xff0c;然后逐步深入了解多头注意力、多头掩码注意力、融合注意力等概念及作用。 注意力机制&#xff08;Attension&#xff09; 背景 深度学…

如何在立创EDA的PCB电路板导入logo图案

1、首先制作好logo图案&#xff0c;一般为公司logo图标&#xff0c;如下图 2、打开立创EDA的PCB文件&#xff0c;如下图 3、将PCB的图层切换到丝印层&#xff1a; 4、然后选择EDA菜单栏的放置---图片&#xff1a; 5、进入后点击选择图片&#xff0c;将logo图片导入&#xff0c;…

人生低谷来撸C#--022 winfrom 和WPF

1、简单介绍 标题其实是写错了&#xff0c;是winform,不是winfrom&#xff0c;如果再准确点&#xff0c;应该是 WinForms&#xff08;复数形式&#xff09;&#xff0c;它代表的是 Windows Forms 技术&#xff0c;用于在 .NET Framework 中创建桌面应用程序的用户界面。在 Vis…

数据结构——八大排序

一.排序的概念和其应用 1.1排序的概念 排序&#xff1a;排列或排序是将一组数据按照一定的规则或顺序重新组织的过程&#xff0c;数据既可以被组织成递增顺序&#xff08;升序&#xff09;&#xff0c;或者递减顺序&#xff08;降序&#xff09;。稳定性&#xff1a;假定在待…

Prometheus监控的搭建(ansible安装——超详细)

目录 1.各组件功能介绍 2.安装批量部署工具ansbile 3.执行服务器 4.各服务器间做免密 5.下载安装包 5.1Prometheus的下载的下载地址 5.2exporter的下载地址 5.3grafana的下载地址 6.编辑ansible需要的配置文件 7.编写ansible文件 8.验证执行结果 今天和大家分享一下…

网站在线查询工具箱源码分享

终极网络工具系统”(SAAS)&#xff0c;是一款功能强大的PHP脚本在线查询工具。本版集合了超过470种快速且易用的Web工具&#xff0c;为日常任务处理和开发人员提供了极大的便利。作为一款综合性的网络工具系统&#xff0c;66toolkit不仅满足了用户的基本网络需求&#xff0c;更…

Java面试题 -- 为什么重写equals就一定要重写hashcode方法

在回答这个问题之前我们先要了解equals与hascode方法的本质是做什么的 1. equals方法 public boolean equals(Object obj) {return (this obj);}我们可以看到equals在不重写的情况下是使用判断地址值是否相同 所以默认的 equals 的逻辑就是判断的双方是否引用了一个对象&am…

【EI会议征稿】第四届高性能计算与通信工程国际学术会议(HPCCE 2024)

出版出版 【SPIE出版 | 往届会后3个月内完成EI检索】 第四届高性能计算与通信工程国际学术会议(HPCCE 2024) 2024 4th International Conference on High Performance Computing and Communication 第四届高性能计算与通信工程国际学术会议&#xff08;HPCCE 2024&#xf…

使用Chainlit接入通义千问快速实现一个自然语言转sql语言的智能体

文本到 SQL 让我们构建一个简单的应用程序&#xff0c;帮助用户使用自然语言创建 SQL 查询。 最终结果预览 ​ 先决条件 此示例有额外的依赖项。你可以使用以下命令安装它们&#xff1a; pip install chainlit openai​ 导入 应用程序 from openai import AsyncOpenAI…

扩展------零拷贝技术(Mmap,SendFile)

什么是零拷贝 零拷贝&#xff08;Zero-Copy&#xff09;是一种计算机操作技术&#xff0c;旨在减少数据在内存之间的拷贝次数&#xff0c;以提高数据传输的效率和性能。 传统的IO模式&#xff1a; 模拟网络传输数据运行过程&#xff1a; 用户态read()发起系统调用&#xff0c…

Flink中上游DataStream到下游DataStream的内置分区策略及自定义分区策略

目录 全局分区器GlobalPartitioner 广播分区器BroadcastPartitioner 哈希分区器BinaryHashPartitioner 轮询分区器RebalancePartitioner 重缩放分区器RescalePartitioner 随机分区器ShufflePartitioner 转发分区器ForwardPartitioner 键组分区器KeyGroupStreamPartitio…

力扣SQL50 第二高的薪水 ifnull() 分页

Problem: 176. 第二高的薪水 &#x1f468;‍&#x1f3eb; 参考题解 Code select ifNull((select distinct salaryfrom employeeorder by salary desclimit 1,1),null) as SecondHighestSalary

【Python数据结构与算法】分治----汉诺塔问题

题目&#xff1a;汉诺塔问题 描述 古代有一个梵塔&#xff0c;塔内有三个座A、B、C&#xff0c;A座上有n个盘子&#xff0c;盘子大小不等&#xff0c;大的在下&#xff0c;小的在上。三个座都可以用来放盘子。有一个和尚想把这n个盘子从A座移到C座&#xff0c;但每次只能允许移…

AWS SES 认证策略设置全攻略:轻松掌握简单步骤!

最近&#xff0c;我有机会设置 Amazon Simple Email Service&#xff08;以下简称&#xff1a;SES&#xff09;的认证策略&#xff0c;所以这次写下来作为备忘。 前言 Amazon Simple Email Service&#xff08;SES&#xff09;是一项通过 API 端点或 SMTP 接口进行邮件发送的服…

MySQL:VIEW视图

概述 MySQL 视图&#xff08;View&#xff09;是一种虚拟存在的表&#xff0c;同真实表一样&#xff0c;视图也由列和行构成&#xff0c;但视图并不实际存在于数据库中。行和列的数据来自于定义视图的查询中所使用的表&#xff0c;并且是在使用视图时动态生成的。 数据库中只…

从Notion Sites的推出,分析SaaS服务发展浪潮

引言 前段时间&#xff0c;Notion发布了新功能“Notion Sites”&#xff0c;允许用户直接在Notion中编辑页面并将其作为网站发布。其实在此之前&#xff0c;一些SaaS&#xff08;软件即服务&#xff09;软件也具有该功能&#xff0c;比如HelpLook AI知识库、Squarespace、Wix等…

buu做题(13)

[BSidesCF 2019]Kookie 给了一个账户: cookie / monster 根据提示, 我们需要以 admin 的身份登录 抓个包 , 可以发现一个奇怪的地方, Set-Cookie: usernamecookie; 以这样的方式确定登录的用户, 尝试伪造一下 直接 加上一个请求头: Cookie:usernameadmin 就可以得到flag 也…