排序(数据结构)

排序(数据结构)

一. 排序概念及运用

排序在数据结构中是非常重要的一部分,所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作

在生活中也有很多的应用,比如当我们搜索一款产品时候,我们可以选择按销量多少的顺序来给我们推荐产品,也可以按照价格高低来给我们推荐产品,所以排序在生活中也是很常见的。

1.1插入排序

(1)直接插入排序

上面就是一些常见的排序算法,首先我们来认识一下插入排序,插入排序又分为直接插入排序和希尔排序,直接插入排序是比较好理解的,比如我们日常生活中的扑克牌游戏,当我们拿到牌的时候我们会习惯性的直接将牌按我们想要的顺序排列,如下:

 

那么希尔排序又是怎么回事呢? 我还是用一张清晰的思路图来向大家展示:

void InitSort(int* arr, int n) { for (int i = 0; i < n-1; i++) { int end = i; int tmp = arr[end + 1]; while (end >= 0) { if (arr[end] > tmp) { arr[end + 1] = arr[end]; end--; } else { break; } } arr[end + 1] = tmp; } }

那么对于直接插入来说,这个算法的时间复杂度是多少呢?大家可以看我们的代码是有两层嵌套的,也就是说如果有最坏的情况发生的话,我们的时间复杂度为O(n^2),但是最好的情况是O(n)。

(2)希尔排序

我们在直接插入排序中,当数组为降序时,我们的时间复杂度会高一点,那么有没有什么办法可以得到优化呢?此时就要说我们的希尔排序了,希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数(通常是gap = n/3+1),把待排序文件所有记录分成各组,所有的距离相等的记录分在同一组内,并对每一组内的记录进行排序,然后gap=gap/3+1得到下一个整数,再将数组分成各组,进行插入排序,当gap=1时,就相当于直接插入排序。它是在直接插入排序算法的基础上进行改进而来的,综合来说它的效率肯定是要高于直接插入排序算法的。

总结下来就是第一步预排序,第二步直接插入排序

void ShellSort(int* arr, int n) { int gap = n; while (gap > 1) { gap = gap / 3 + 1; for (int i = 0; i < n - gap; i++) { int end = i; int tmp = arr[end + gap]; while (end >= 0) { if (arr[end] > tmp) { arr[end + gap] = arr[end]; end -= gap; } else { break; } } arr[end + gap] = tmp; } } }

 对于希尔排序,我们直接的思路是比较好理解的,但是如果我们写成代码的话,是有点不好理解的,尤其是对于gap分组再嵌套进入循环,大家可以借助画图的方法深入理解一下。对于希尔排序的时间复杂度,希尔排序时间复杂度不好计算,因为 gap 的取值很多,导致很难去计算,因此很多书中给出的希尔排序的时间复杂度都不固定。但是外层循环的时间复杂度可以直接给出为: O(log2 n) 或者 O(log3 n) ,即 O(log n)。总之希尔排序的效率是高于直接插入排序的。

1.2 选择排序

 

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

(1)直接选项排序

1. 在元素集合 array[i]--array[n-1] 中选择关键码最大(小)的数据元素。2. 若它不是这组元素中的最后一个(第一个)元素,则将它与这组元素中的最后一个(第⼀          个)元素交换。3. 在剩余的 array[i]--array[n-2](array[i+1]--array[n-1]) 集合中,重复上述步骤,直到集合      剩余1个元素。
Swap(int* a, int* b) { int temp; temp = *a; *a = *b; *b = temp; } void SelectSort(int* arr, int n) { for (int i = 0; i < n; i++) { int begin = i; int mini = i; //找最小的值 for (int j = i + 1; j < n; j++) { if (arr[j] < arr[mini]) { mini = j; } } //找到最小的值了,i和mini位置的数据进行交换 Swap(&arr[i], &arr[mini]); } }

 这一部分的算法思路还是很好理解的,我们进行了两次嵌套循环,在每一次中找到最小的值,然后将最小的值放在第一位,同时这个算法的时间复杂度跟我们的直接插入排序是一样的,最差情况是O(n^2),但是我们能不能换一个思路,我们在找最小值的情况下能不能直接找最大值,同时进行寻找,那么我们的时间效率会不会提高呢?

void SelectSort2(int* arr, int n)//优化 { int begin = 0; int end = n - 1; while (begin < end) { int mini = begin, maxi = begin; for (int i = begin+1; i <= end; i++) { if (arr[i] > arr[maxi]) { maxi = i; } if (arr[i] < arr[mini]) { mini = i; } } Swap(&arr[mini], &arr[begin]); Swap(&arr[maxi], &arr[end]); ++begin; --end; } }

 这是我们按照之后的思路写的算法,根据我的代码,我们是同时找最小值和最大值,最后在交换,但是代码出现了问题,最后并没有按我们想要的排序,那么问题到底出现在哪了呢?

 所以我们还要处理这种特殊的情况,我们就要在交换之前再加上一个if条件:

直接选择排序的特性总结:1. 直接选择排序思考非常好理解,但是效率不是很好。实际中很少使用。2. 时间复杂度: O(n^2 )。3. 空间复杂度: O(1)。

(2)堆排序

堆排序也是属于选择排序的一种,堆排序(Heapsort)是指利用堆积树(堆)这种数据结构所设计的一种排序算法,它是选择排序的一种。它是通过堆来进行选择数据。需要注意的是排升序要建大堆,排降序建小堆。在前面学习堆的时候我们也详细的讲解过堆排序的原理思路以及详细的代码展示,大家可以去看我之前写的。那么堆排序的时间复杂度是O(nlogn)。

对于今天的两大种排序算法来说,在插入排序中,希尔排序是直接插入排序的优化,效率提高了不少,在选择排序中呢,我们的直接选择排序的时间复杂度是比较高的,也就是说这个排序算法的效率是比较低的,在平时的计算中我们是不选择的,但是我们也要了解这种算法。

 

 

 

Read more

机器人逆运动学:从SVD到IK算法

机器人逆运动学:从SVD到IK算法

引言 最近接触的机器人项目需要实现在特定约束下的逆运动学解算,而直接套用目前大多数开源IK算法(如KDL/TRAC IK等)或多或少都存在一些问题,因此需要自行实现迭代IK并添加特定的约束.然而,目前普遍教科书都倾向于介绍解析解IK,对数值IK更多是从网络博客收集整理获得,因此决定写下本文将这部分的知识作一个总结. 本文将从基础的线性代数SVD开始介绍,逐步过渡到数值IK的求解中,并以KDL的源码为例进一步剖析实际应用时的写法. SVD与最小二乘法 SVD是工程数学常用的工具,数学上看起来只是对矩阵做分解,但其在工程上可应用的地方很多,如奇异值和特征向量可以作为降维(PCA),除此以外分解后的矩阵有良好的性质方便求逆. 下面将详细介绍SVD如何用于求逆. 线性代数常见的一个问题: A x = b (1.1) Ax=b \tag{1.1} Ax=b(1.1) 求 x x x最直观的一个理解是对矩阵 A A A求逆,其解就是 A − 1 b A^

By Ne0inhk
在 Mac Mini M4 上本地跑大模型(Ollama + Llama + ComfyUI + Stable Diffusion | Flux)

在 Mac Mini M4 上本地跑大模型(Ollama + Llama + ComfyUI + Stable Diffusion | Flux)

Mac Mini M4 配备了苹果自家研发的 M1/M2/M4 芯片,具有强大的处理能力,能够支持本地跑一些大模型,尤其是在使用如 Ollama、Llama、ComfyUI 和 Stable Diffusion 这类 AI 相关工具时,性能表现非常好。本教程将指导你如何在 Mac Mini M4 上本地部署并运行这些大模型,涵盖从环境搭建到使用的全流程。 一、准备工作 1. 确保系统更新 确保你的 macOS 版本已更新到最新的版本(例如 macOS 13.0 以上),这将确保兼容性和性能。 安装 Homebrew(macOS 包管理工具) Homebrew 是 macOS 上非常流行的包管理工具,它帮助你方便地安装各种软件。在终端中输入以下命令来安装

By Ne0inhk
腾讯QQ官方炸场!OpenClaw一键建5个机器人,个人号直接上手|实战教程

腾讯QQ官方炸场!OpenClaw一键建5个机器人,个人号直接上手|实战教程

文章目录 * 前言 * 一、OpenClaw是个啥?你的"数字长工" * 二、为什么说这次QQ"炸场"了? * 三、实操环节:从0到1,手把手养出你的AI小弟 * 3.1 在QQ开放平台"造人" * 3.2 给机器人找个"肉身"(部署OpenClaw) * 方案A:云服务器一键部署(推荐新手) * 方案B:宝塔面板可视化安装(适合有服务器的站长) * 方案C:本地Docker部署(适合极客) * 3.3 关键的"认亲"三步走 * 3.4 加好友,

By Ne0inhk