异世界历险之数据结构世界(排序(插入,希尔,堆排))

前言

在这里插入图片描述

介绍

插入排序

基本知识:
直接插入排序是一种简单的插入排序法,其基本思想是:
把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列

在这里插入图片描述

直接插入排序的特性总结:

  1. 元素集合越接近有序,直接插入排序算法的时间效率越高
  2. 时间复杂度:O(N^2)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

实现

void InsertSort(int*arr,int n)
{for (int i = 1; i < n; i++){int tmp = arr[i];int end = i - 1;while (tmp < arr[end]){arr[end + 1] = arr[end];end--;}arr[end + 1] = tmp;}}

解析:1.外层 for 循环控制遍历每个待插入的元素,从下标 1 开始(因为下标 0 视为初始的已排序区)
2. tmp 暂存当前要插入的元素。
end 表示已排序部分的末尾元素下标,用来向左比较寻找插入位置。
3.当当前元素 tmp 小于已排序区的元素 arr[end],说明还没找到插入位置:
将较大的元素右移一位,给 tmp 腾出空间;
end-- 继续向左查找。

4.找到插入位置后,将 tmp 放入空出来的位置,即 end + 1

希尔排序

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

在这里插入图片描述

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经 接近有序的了,这样就会很快。

实现

void ShellSort(int*arr,int n)
{ for(int gap = n/2;gap>0;gap/=2){  for(int i = gap;i<n;i++){ int tmp = arr[i];int end = i-gap;while(end>=0 && arr[end]>tmp){arr[end+gap] =arr[end];end -= gap;}arr[end+gap] = tmp;}}
}
解析
for(int gap = n/2;gap>0;gap/=2)

设定初始间隔 gap = n/2,后续每次缩小一半。
这样每轮都能把当前数组变得更“接近有序”。
最后当 gap == 1 时,其实就是普通的插入排序,但效率更高!

for (int i = gap; i < n; i++)

从当前 gap 开始往后遍历数组。
为啥不是 i=0?因为我们要比较 arr[i] 和它 gap 之前的数,即 arr[i - gap],所以 i 至少得 ≥ gap。

arr[end + gap] = arr[end];
end -= gap;

把大的元素往后挪出一个 gap 的位置。
指针继续往前 gap 个单位看下一个数。

arr[end + gap] = tmp;

找到该插入的位置了,把 tmp 插进去。
完成一个元素在当前 gap 下的插入排序。

实战演示

数组排序OJ
在这里插入图片描述

解答
void ShellSort(int*arr,int n)
{ for(int gap = n/2;gap>0;gap/=2){  for(int i = gap;i<n;i++){ int tmp = arr[i];int end = i-gap;while(end>=0 && arr[end]>tmp){arr[end+gap] =arr[end];end -= gap;}arr[end+gap] = tmp;}}
}int* sortArray(int* nums, int numsSize, int* returnSize) {int* arr = (int*)malloc(sizeof(int)*numsSize);for(int i = 0;i<numsSize;i++){arr[i]=nums[i];}InsertSort(arr,numsSize);*returnSize = numsSize;return arr;
}

希尔排序总结:

核心思路:先按大 gap 做分组插入排序,逐步缩小 gap 到 1。
时间复杂度:平均 ≈ O(n¹·³~n¹·⁵),最坏 O(n²);效率取决于 gap 序列。
空间复杂度:O(1) 原地排序。
稳定性:不稳定,同值元素位置可能改变。

希尔排序补充

1.反向插排希尔
void HalfShellSort(int* arr, int n)
{int gap = 3;for (int i = 0; i < n - gap; i++){int end = i;int tmp = arr[i + gap];while (end >= 0 && arr[end] > tmp){arr[end + gap] = arr[end];end -= gap;}arr[end + gap] = tmp;}
}

差异:

for (int i = 0; i < n - gap; i++)
{int end = i;int tmp = arr[i + gap];
}
for(int i = gap;i < n;i++){ int tmp = arr[i];int end = i-gap;}

解释:
方案一是正常思维以0为起点,即end为主角,end+gap 是tmp的位置,故为了不越界·i<n-gap。
方案二是以第二个gap为i的开始,即tmp为主角,tmp始终是end的后一个gap,所以i<n,不存在越界问题。

2.多重循环希尔
void ShellSort(int* arr, int n)
{for (int gap = n / 2; gap > 0; gap /= 2){for (int j = 0; j < gap; j++){for (int i = j; i < n - gap; i+=gap){int tmp = arr[i+gap];int end = i;while (end >= 0 && arr[i] > tmp){arr[end + gap] = arr[end];end -= gap;}arr[end + gap] = tmp;}}}
}

差异:

for (int j = 0; j < gap; j++)for (int i = j; i < n - gap; i+=gap)
for(int i = 0;i<n-gap;i++)

方案一比方案二多了一层循环
原因分析: 方案一是以gap将全部分为gap个集合,每个集合内进行希尔排序。
例如:以gap==3 为例:
分为:0开头集合,1开头集合,2开头集合 以这种形式进行排序。
方案二则是按顺序一个一个排。
二者没有任何区别,时间复杂度和空间复杂度一样。

堆排序

基本知识:
堆排序即利用堆的思想来进行排序,总共分为两个步骤:

  1. 建堆
    升序:建大堆
    降序:建小堆
  2. 利用堆删除思想来进行排序

堆的复习
向上调整函数(AdjustUp)
向下调整函数(AdjustDown)
堆插入

实现

1.建堆
方案一:

void AdjustUp(int* arr,int child)
{int parent = (child - 1) / 2;while (child>0){if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);child = parent;parent = (child - 1) / 2;}else{break;}}
}void HeapSort(int*arr,int n)
{for (int i = 1; i < n; i++){AdjustUp(arr, i);}
}

类似于堆插入,从第二个数组中元素开始插入,调整。

方案二:

void AdjustDown(int* arr, int n, int parent)
{int child = 2 * parent + 1;while (child < n){if (child + 1 < n && arr[child] < arr[child + 1]){child++;}if (arr[child] > arr[parent]){Swap(&arr[child], &arr[parent]);parent = child;child = 2 * parent + 1;}else{break;}}
}void HeapSort(int*arr,int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr,n,i);}
}

i == (n-1-1)/2 是尾(最后)叶子的父节点。
向下调整建堆的原理是:
从最后一个非叶子节点开始,逐个对子树进行向下调整,把局部小堆变成大堆,逐层向上构造,最终整个数组就成了一个大堆结构。

在这里插入图片描述

总结:
方法一:向上调整(AdjustUp)
从第1个元素往后扫,每插入一个元素就“向上冒泡”一次,维护堆
时间复杂度:O(n log n)
方法二:向下调整(AdjustDown)
从最后一个非叶子节点开始,逐个节点向下调整整个子树
最终堆顶就是整个数组的最大值(如果建大堆)
时间复杂度:O(n) 更优!

2.排序

void HeapSort(int*arr,int n)
{for (int i = (n - 1 - 1) / 2; i >= 0; i--){AdjustDown(arr,n,i);}int end = n - 1;while (end > 0){Swap(&arr[0], &arr[end]);AdjustDown(arr, end, 0);end--;}
}

在这里插入图片描述
排序如图所示。
1.交换根和尾叶子,把大数放在后面。
2.向下调整,在形成大根堆。
3.循环往复。

总结

八大排序我们学了三个,其余的将逐渐补充丰富。

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

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

相关文章

oracle 数据库中,将几张表的数据按指定日期范围实时同步至同一个数据库的备份表中。

以下是一个Oracle数据库中实现表数据按指定日期范围实时同步至备份表的解决方案。这个方案使用存储过程和触发器组合实现&#xff1a; 1. 创建备份表结构 首先需要为每张需要备份的表创建对应的备份表&#xff0c;结构与原表相同&#xff1a; -- 为原表创建备份表&#xff08;示…

电脑网络连接正常,微信、QQ能正常使用,但无法访问网页?DNS问题的解决方案和背后原理。

文章目录1. 问题背景2. 解决方案2.1 手动刷新DNS2.1.1 Windows版本2.1.2 Mac版本2.2 手动设置DNS服务器2.2.1 Windows版2.2.2 Mac版2.3 其他解决方案3. DNS是什么&#xff1f;3.1 详细解释DNS3.1.1 A distributed, hierarchical database&#xff08;一个分布式和分层数据库结构…

【HTML】图片比例和外部div比例不一致,最大程度占满

图片比例和外部div比例不一致&#xff0c;最大程度占满&#xff0c;并且图片比例不变 其中1.jpg,2.jpg,1.html在同一目录 |-----|- 1.jpg|- 2.jpg|- 1.html1.jpg2.jpg<!DOCTYPE html> <html lang"en"><head><meta charset"UTF-8" /&g…

如何使用python网络爬虫批量获取公共资源数据技术

如何快速批量地获取海量公共资源数据决定了科研的效率。Python网络爬虫是快速批量获取网络数据的重要手段&#xff0c;它按照发送请求、获得页面、解析页面、下载内容、储存内容等流程&#xff1f; 一&#xff1a;Python软件的安装及入门1 Python软件安装及入门1)Anaconda软件安…

Kiro vs Cursor: AI IDE 终极对比指南

概述 随着生成式 AI 革命性地改变了我们编写代码的方式&#xff0c;新一代 AI 驱动的集成开发环境 (IDE) 正在崛起。Kiro 和 Cursor 代表了这一运动的前沿&#xff0c;但它们采用了截然不同的方法。 核心理念对比 特性AWS KiroCursor核心理念结构化开发流程 (Spec-driven)对…

Python获取网页乱码问题终极解决方案 | Python爬虫编码处理指南

在Python网络爬虫开发中&#xff0c;乱码是最常见的问题之一。本文将深入探讨乱码产生的原因&#xff0c;并提供多种有效的解决方案&#xff0c;帮助您彻底解决Python获取网页内容时的乱码问题。常见网页编码格式编码类型使用场景Python解码方式UTF-8现代网站标准编码.decode(u…

Android MTK平台预置多张静态壁纸

执行 adb shell pm list package -f wallpaper 命令&#xff0c;查看壁纸应用路径&#xff1a; /product/app/MtkWallpaperPicker/MtkWallpaperPicker.apkcom.android.wallpaperpicker 结果中带 Mtk 就可确定MTK有对应用进行重构。其源码路径在 vendor/mediatek/proprietary/…

基于Django的个人博客系统开发(开题报告)

毕业论文(设计)开题报告论文(设计)题目 基于Django的个人博客系统开发 1.选题目的和意义 随着云服务器的普及化以及编程培训机构大量涌现,学习网站开发技术以及编程技术,通过租用个人云服务器部署代码,构建个人博客网站,创建学习文档,记录学习过程,与他人交流技术学…

C++ 分配内存释放内存

C 分配内存释放内存一、new、delete、malloc和free最简单的分配内存自定义对象分配和释放内存二、new、delete与虚析构的问题三、一维、二维、多维数值创建和释放一维二维多维四、new的缺点以及连续内存的优点一、new、delete、malloc和free 最简单的分配内存 int* p_m (int*…

奥比中光深度相机开发

一、开发环境准备 1.1 硬件要求 奥比中光深度相机&#xff08;如Astra Pro、Gemini等&#xff09;USB 3.0接口&#xff08;确保数据传输稳定&#xff09;支持OpenGL的显卡&#xff08;可选&#xff0c;用于点云可视化&#xff09; 1.2 软件环境 SDK安装&#xff1a; 从奥比…

标题 “Python 网络爬虫 —— selenium库驱动浏览器

一、Selenium 库核心认知 Selenium 库是 Web 应用程序测试与自动化操作的利器 &#xff0c;能驱动浏览器&#xff08;如 Edge、Firefox 等&#xff09;执行点击、输入、打开、验证等操作 。与 Requests 库差异显著&#xff1a;Requests 库仅能获取网页原始代码&#xff0c;而 …

从实践出发--探究C/C++空类的大小,真的是1吗?

文章目录测试代码VS2022正常运行编译失败GCC总结Author: NemaleSu Data: 2025/07/21 测试环境&#xff1a; Win11&#xff1a;VS2022Ubuntu22.04&#xff1a;gcc (Ubuntu 11.4.0-1ubuntu1~22.04) 11.4.0 相信众多cpper听过太多书籍、视频、文档、博客等资料&#xff0c;说C/C…

数据结构自学Day11-- 排序算法

一、排序算法的概念排序&#xff08;Sorting&#xff09;是指&#xff1a;将一组“无序”的数据&#xff0c;按照某种“顺序规则”排列成“有序”的过程。1、按排序顺序分类&#xff1a;升序&#xff1a;从小到大排列&#xff0c;如 1, 3, 5, 7, 9降序&#xff1a;从大到小排列…

电子元器件—三极管(一篇文章搞懂电路中的三极管)(笔记)(面试考试必备知识点)

三极管的定义及工作原理1. 定义三极管&#xff08;Transistor&#xff09;是一种具有三层半导体材料&#xff08;P-N-P 或 N-P-N&#xff09;构成的半导体器件&#xff0c;用于信号放大、开关控制和信号调制等应用。三极管有三个引脚&#xff1a;发射极&#xff08;Emitter&…

数据结构之克鲁斯卡尔算法

前言&#xff1a;和Prim算法一样&#xff0c;Kruskal 算法也是用来生成最小生成树的&#xff0c;这篇文章来学习一下Kruskal算法的实现 一、实现流程 初始化的时候&#xff0c;将所有的边用一个数组存储&#xff0c;并且按权值从小到大进行排序&#xff0c;每次选一个权值最小的…

MongoDB 查询时区问题

MongoDB默认时区是UTC&#xff0c;比北京时区晚八小时&#xff0c;北京时间UTC8h。 // 北京时间的 2024-10-01 08:00:00 // (>) 大于 - $gt // (<) 小于 - $lt // (>) 大于等于 - $gte // (< ) 小于等于 - $lte// Z代表UTC时区1、{"gmtCreate":{"$…

Windows VS2019 编译 Apache Thrift 0.15.0

随着微服务架构的普及,高效的跨语言远程过程调用(RPC) 成为了构建分布式系统的重要基础。Apache Thrift 是 Facebook 开源的一个轻量级、高性能的 RPC 框架,它允许开发者通过一个通用的接口定义语言(IDL)来定义服务接口和数据结构,并自动生成多种语言的客户端和服务端代…

搭建种草商城框架指南

一、引言在当今电商市场&#xff0c;种草商城以其独特的社交化购物模式受到越来越多用户的喜爱。搭建一个功能完善、体验良好的种草商城框架&#xff0c;需要综合考虑前端界面、后端服务、数据库设计等多个方面。本文将为你详细介绍搭建种草商城框架的关键要点和技术选型。二、…

docker--挂载

设置容器的挂载 需要注意 挂载行为会覆盖容器目标目录的原有内容(未验证)。 查看容器的挂载情况 在容器外部查看: docker inspect <容器名或容器ID> | grep -A n "Mounts" -A n 的含义 -A 是 --after-context 的缩写,表示显示匹配行及其后 n 行。 "Mo…

以Streamable HTTP方式访问mcp server的过程

一、mcp server 部署 使用fastmcp框架 部署 mcp server&#xff0c; 以下是源代码 # 引入 fastmcp 依赖包 from fastmcp import FastMCP# 新建fastmcp实例&#xff0c; 名字叫做 weather mcp FastMCP("weather")mcp.tool(name"weather", tags{"weath…