排序算法复习——包括插入排序、希尔排序、冒泡排序、快排(包括霍尔法、挖坑法、快慢指针法)、堆排、选择排序、归并排序等 (代码采用c/c++混编)

1.插入排序

        插入排序就像我们打斗地主的时候,有一大把牌我们来不及理,就会一张一张的拿然后把拿到的牌放到合适的位置。

        对于插入排序我们可以将待排序的数组理解为那一堆没有整理的牌,将排序好的部分理解为手上的牌,对于第i张牌我们的i-1张牌是理好的,那么我们只需要将第i张的大小与前面的第i-1张牌比较就可以找到他的位置,具体实现如下

void InsertSort(vector<int> &a, int n)
{for (int i = 1; i < n; i++){int end = i - 1;int tmp = a[i];while (end >= 0){if (a[end] > tmp){a[end + 1] = a[end];end--;}elsebreak;}a[end + 1] = tmp;}
}

2.希尔排序

        希尔排序是对插入排序的优化,对于插入排序来讲如果数组是有序的那么插入排序的时间复杂度是O(N),那么如果我们让数组尽可能的有序其实就提升了插入排序的效率,根据这个想法希尔排序就诞生了。

        希尔大佬将待排序的数组根据某个整数分成n组,这n组每一组都采用插入排序,先对这n组排序然后缩小n值再对这n组排序,直到n == 1,其实n == 1的时候就是插入排序,再希尔排序中我们将这个整数称为gap,一般初始gap = 数组大小/2也有的是 gap = 数组大小/3+1,当然了这两种方法的效率应该差的不大具体见下面的图片

void ShellSort(vector<int> &a, int n)
{int gap = n;while (gap > 1){gap /= 2;for (int i = 0; i < gap; i++){for (int j = i; j < n; j += gap){int end = j, tmp;if (j + gap < n)tmp = a[j + gap];elsebreak;while (end >= 0){if (a[end] > tmp){a[end + gap] = a[end];end -= gap;}elsebreak;}a[end + gap] = tmp;}}}
}

        我的代码可能不是那么易懂,所以我在这里讲解一下       

        首先我的gap其实第一次分的组数是n/2,对于这gap组我是通过他们的头部来确定整个数组的,就是我的第一个for循环,然后每个组的头部加上gap其实就是这个组内下一个元素的位置,这个时候是有边界条件的如果+gap以后的数大于或者等于数组大小那么就可以不管他了,这就是第二个for循环然后while里是插入排序的逻辑

3.选择排序(很抽象的一个排序,时间复杂度稳定O(N^2))

        简单来说就是遍历数组找到最小的数将他和待排序区间的头元素交换,我们可以进行一定的优化,比如我们既然已经遍历了,就随便把最大的元素也找了一次排两个数效率就提升了一些。

        但是优化后存在一些问题比如你的最大值的位置在待排序左端,但是我们的最小值是需要和待排序左端进行交换的那么交换后最大值的位置是不是就到了原来最小值的位置。所以我们在进行最大值交换的时候需要先判断最大值的位置是不是待排序左端,如果是那么最大值的位置就要修正为原最小值的位置。

        这里先提供一份不优化版的

void SelectSort(vector<int> &a, int n)
{for (int i = 0; i < n; i++){int tmp = a[i], tmpps = i;for (int j = i + 1; j < n; j++){if (a[j] < tmp){tmpps = j;tmp = a[j];}}Swap(a[tmpps], a[i]);}
}

        这里是优化版本

void SelectSort(vector<int> &a, int n, int level)
{int left = 0, right = n - 1;while (left < right){int min = a[left], max = a[right];int minps = left, maxps = right;for (int i = left + 1; i < right; i++){if (a[i] <= min){min = a[i];minps = i;}if (a[i] > max){max = a[i];maxps = i;}}// 这里需要修正  如当left与maxps相等时第一次交换会导致a[maxps]的值改变到a[minps]Swap(a[left], a[minps]);if (left == maxps)maxps = minps;Swap(a[right], a[maxps]);left++;right--;}
}

4.堆排序

        这里先讲一些堆排序的前置知识,堆的底层是数组,但是逻辑结构是完全二叉树,然后根据完全二叉树的父子关系,以及向上调整完成建堆,然后通过向下调整完成排序。

        

        这是一个大根堆向下调整做降序,所谓向下调整其实就是先将根与最末节点交换然后对除最末节点以外的堆的根进行向下调整,具体就是将这个根与他的子节点中大的的那个交换(如果跟的数组序号是parent那么左孩子节点的数组序号就是child = parent*2+1右孩子就是child+1)直到到叶子位置或者比两个孩子都大时就结束了。

        代码部分包括建堆

// 向上调整建堆
void AdjustUp(vector<int> &a, int n)
{for (int i = 1; i < n; i++){int child = i, parent = (i - 1) / 2;while (child > 0){if (a[child] > a[parent]){Swap(a[child], a[parent]);child = parent;parent = (child - 1) / 2;}elsebreak;}}
}// 从root位置开始向下调整
void AdjustDwon(vector<int> &a, int n, int root)
{int parent = root, child = parent * 2 + 1;while (child < n){if (child + 1 < n && a[child + 1] > a[child])child++;if (a[child] > a[parent]){Swap(a[child], a[parent]);parent = child;child = parent * 2 + 1;for (auto ch : a)std::cout << ch << " ";std::cout << std::endl;}elsebreak;}
}
// 堆排序  堆的逻辑结构是完全二叉树  底层结构是数组
// 根据parent 可以找到左孩子节点child = parent*2+1
void HeapSort(vector<int> &a, int n)
{AdjustUp(a, n);for (auto ch : a)cout << ch << " ";std::cout << std::endl;for (int i = n - 1; i >= 0; i--){std::cout << "a[0] : " << a[0] << " " << "a[" << i << "] : " << a[i] << "::";Swap(a[0], a[i]);AdjustDwon(a, i, 0);for (auto ch : a)cout << ch << " ";std::cout << std::endl;}
}

5.冒泡排序

        比较简单就是从数组的每一个位置开始将该位置的数与后面的数比较如果该位置大就交换,反之不做处理,直到比较到数组末尾单趟结束,然后从上次开始的位置的后一个位置开始重复。

void BubbleSort(vector<int> &a, int n)
{for (int i = 0; i < n; i++){for (int j = 0; j < n-i; j++){if (a[j-1] > a[j])Swap(a[j-1], a[j]);}}
}

6.快速排序

6.1 霍尔大佬版

        简单来说就是选定一个key然后有一个left是这段区域的开头,一个right是这段区域的结尾,然后right先走直到找到小于key的位置停下,然后left开始走直到找到大于key的位置然后交换这两个位置的值,然后重复这个过程直到right和left相遇就将相遇位置的值与key位置的值交换。这样单趟快排就完成了,通过现在key的位置可以将数组划分为两个区域在对这两个区域快排,不断重复就可以完成排序

        

        这里keyi值的选取有三数取中法即:left、rigth、(left+right)/2 的中间值(对应在数组中的值的大小来比较的)来当key这样是为了提高快排在数组相对有序的时的效率。

// 2. 三数取中int GetMidNumi(vector<int> &a, int left, int right)
{int numi = (right + left) / 2;if (a[left] > a[right]){if (a[right] >= a[numi])return right;else{if (a[left] >= a[numi])return numi;elsereturn left;}}else{if (a[left] >= a[numi])return left;else{if (a[right] >= a[numi])return numi;elsereturn right;}}
}void PartSort1(vector<int> &a, int left, int right)
{if (left >= right)return;int begin = left, end = right;// int randi = left + (rand() % (right-left));     随机取keyiint randi = GetMidNumi(a, left, right); // 三数取中Swap(a[left], a[randi]);int keyi = left;while (begin < end){if (a[end] < a[keyi]){if (a[begin] > a[keyi]){Swap(a[begin], a[end]);}else{begin++;continue;}}end--;}// 走出循环说明end和begin相遇Swap(a[end], a[keyi]);keyi = end;PartSort1(a, left, keyi);PartSort1(a, keyi + 1, right);
}

6.2 挖坑法

        其实说白了就是先保存keyi对应的数组位置的值key,然后在right找到小于key就直接放到keyi对应位置上然后坑的位置就到了当前right的位置,然后left开始走找到大于key的值的位置就直接将值放到right的位置同时坑的位置到了left重复这个过程直到相遇将key放到相遇位置剩下的和霍尔大佬一样

        

// 快速排序挖坑法
void PartSort2(vector<int> &a, int left, int right)
{if (left >= right)return;int keyi = left, key = a[left];int begin = left, end = right;while (begin < end){while (begin < end && a[end] >= key)end--;a[keyi] = a[end];keyi = end;while (begin < end && a[begin] <= key)begin++;a[keyi] = a[begin];keyi = begin;}a[keyi] = key;PartSort2(a, left, keyi);PartSort2(a, keyi + 1, right);
}

6.3 前后指针法

        cur初始化在prev的后一个位置,cur先走cur找小于key的位置,prev的位置不能超过cur,cur不能超出区域,其实就是当cur与prev相差大于一时,我们交换他们两个的值,然后让cur继续走找小当cur刚好越界时prev的位置就是key应该在的位置

// 快速排序前后指针法
void PartSort3(vector<int> &a, int left, int right)
{if (left >= right)return;int keyi = left;int prev = left, cur = left + 1;while (cur <= right){// if(cur <= right) Swap(a[cur++],a[prev++]);if (a[cur] < a[keyi] && ++prev != cur)Swap(a[prev], a[cur]);cur++;}Swap(a[keyi], a[prev]);keyi = prev;PartSort3(a, left, keyi);PartSort3(a, keyi + 1, right);
}

7.归并排序

        其是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有 序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。

        实现起来类似牛客网上的一道合并两个链表的题

合并两个排序的链表_牛客题霸_牛客网 (nowcoder.com)

        

void _MergeSort(vector<int> &a, int left, int right, vector<int> &tmp)
{if (left >= right)return;int mid = (left + right) / 2;_MergeSort(a, left, mid, tmp);_MergeSort(a, mid + 1, right, tmp);int i = left;int begin1 = left, end1 = mid;int begin2 = mid + 1, end2 = right;while (begin1 <= end1 && begin2 <= end2){if (a[begin1] < a[begin2])tmp[i++] = a[begin1++];elsetmp[i++] = a[begin2++];}while (begin1 <= end1)tmp[i++] = a[begin1++];while (begin2 <= end2)tmp[i++] = a[begin2++];for (int i = left; i <= right; i++)a[i] = tmp[i];
}// 归并排序递归实现
void MergeSort(vector<int> &a, int n)
{std::vector<int> tmp(n);_MergeSort(a, 0, a.size() - 1, tmp);
}

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

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

相关文章

RocketMQ 5.0安装部署

0.前言 在微服务架构逐渐成为主流的今天&#xff0c;消息队列如同数字世界的快递员&#xff0c;承担着系统间高效通信的重要使命。 Apache RocketMQ 自诞生以来&#xff0c;因其架构简单、业务功能丰富、具备极强可扩展性等特点被众多企业开发者以及云厂商广泛采用。历经十余…

Jetson Agx Orin平台preferred_stride调试记录--1924x720图像异常

1.问题描述 硬件: AGX Orin 在Jetpack 5.0.1和Jetpack 5.0.2上测试验证 图像分辨率在1920x720和1024x1920下图像采集正常 但是当采集图像分辨率为1924x720视频时,图像输出异常 像素格式:yuv_uyvy16 gstreamer命令如下 gst-launch-1.0 v4l2src device=/dev/video0 ! …

【玩转全栈】----Django模板语法、请求与响应

目录 一、引言 二、模板语法 三、传参 1、视图函数到模板文件 2、模板文件到视图函数 四、引入静态文件 五、请求与响应 ?1、请求 2、响应 六、综合小案例 1、源码展示 2、注意事项以及部分解释 3、展示 一、引言 像之前那个页面&#xff0c;太过简陋&#xff0c;而且一个完整…

#渗透测试#批量漏洞挖掘#CyberPanel面板远程命令执行漏洞(CVE-2024-51567)

免责声明 本教程仅为合法的教学目的而准备,严禁用于任何形式的违法犯罪活动及其他商业行为,在使用本教程前,您应确保该行为符合当地的法律法规,继续阅读即表示您需自行承担所有操作的后果,如有异议,请立即停止本文章读。 目录 一、漏洞特征与影响 二、修复方案与技术细…

C++多态

目录 多态的概念多态的定义及实现协变析构函数的重写通过一段代码理解多态C11 final 和 override重载、覆盖(重写)、隐藏(重定义)的对比多态调用原理单继承中的虚函数表抽象类多继承中的虚函数表 多态的概念 概念&#xff1a;通俗来说&#xff0c;就是多种形态&#xff0c;具体…

PosgreSQL比MySQL更优秀吗?

一日&#xff0c;一群开发者对PosgreSQL是不是比MySQL更优秀进行了激烈的辩论&#xff0c;双方吵的都要打起来了 正方有以下理由&#xff1a; PostgreSQL严格遵循SQL标准规范&#xff0c;相较MySQL在语法兼容性和功能完整性方面展现出更强的体系化设计&#xff0c;尤其在事务处…

『大模型笔记』Jason Wei: 大语言模型的扩展范式!

Jason Wei: 大语言模型的扩展范式! 文章目录 一. What is scaling and why do it?1. 什么是Scaling?2. 为什么要Scaling?二. Paradigm 1: Scaling next-word prediction1. 下一个词预测2. 极限多任务学习3. Why does scaling work?三. The challenge with next-word predi…

TCP协议(Transmission Control Protocol)

TCP协议&#xff0c;即传输控制协议&#xff0c;其最大的特征就是对传输的数据进行可靠、高效的控制&#xff0c;其段格式如下&#xff1a; 源端口和目的端口号表示数据从哪个进程来&#xff0c;到哪个进程去&#xff0c;四位报头长度表示的是TCP头部有多少个4字节&#xff0c;…

瑞萨RA-T系列芯片ADCGPT功能模块的配合使用

在马达或电源工程中&#xff0c;往往需要采集多路AD信号&#xff0c;且这些信号的优先级和采样时机不相同。本篇介绍在使用RA-T系列芯片建立马达或电源工程时&#xff0c;如何根据需求来设置主要功能模块ADC&GPT&#xff0c;包括采样通道打包和分组&#xff0c;GPT触发启动…

TraeAi上手体验

一、Trae介绍 由于MarsCode 在国内由于规定限制&#xff0c;无法使用 Claude 3.5 Sonnet 模型&#xff0c;字节跳动选择在海外推出 Trae&#xff0c;官网&#xff1a;https://www.trae.ai/。 二、安装 1.下载安装Trae-Setup-x64.exe 2.注册登录 安装完成后&#xff0c;点击登…

三层渗透测试-DMZ区域 二三层设备区域

DMZ区域渗透 信息收集 首先先进行信息收集&#xff0c;这里我们可以选择多种的信息收集方式&#xff0c;例如nmap如此之类的&#xff0c;我的建议是&#xff0c;可以通过自己现有的手里小工具&#xff0c;例如无影&#xff0c;密探这种工具&#xff0c;进行一个信息收集。以免…

DeepSeek-R1:通过强化学习激励大模型的推理能力

大家读完觉得有帮助记得关注和点赞&#xff01;&#xff01;&#xff01; DeepSeek 第一代推理模型&#xff08;reasoning models&#xff09; &#xff08;所以缩写为 R1&#xff09;的设计和训练过程&#xff1a; 要理解 DeepSeek-R1 的创新之处&#xff0c;可以先阅读 如何训…

演绎推理及其与数学的关系介绍

演绎推理及其与数学的关系介绍 什么是演绎推理&#xff1f; 演绎推理&#xff08;Deductive Reasoning&#xff09;是一种逻辑推理方法&#xff0c;它从一般性的规则或前提出发&#xff0c;得出一个具体的、必然正确的结论。换句话说&#xff0c;只要前提&#xff08;Premise&…

【git】工作场景下的 工作区 <-> 暂存区<-> 本地仓库 命令实战 具体案例

&#x1f680; Git 工作区 → 暂存区 → 本地仓库 → 回退实战 Git 的核心流程是&#xff1a; &#x1f449; 工作区&#xff08;Working Directory&#xff09; → git add → 暂存区&#xff08;Staging Area&#xff09; → git commit → 本地仓库&#xff08;Local Repos…

胶囊网络动态路由算法:突破CNN空间局限性的数学原理与工程实践

一、CNN的空间局限性痛点解析 传统CNN的瓶颈&#xff1a; 池化操作导致空间信息丢失&#xff08;最大池化丢弃85%激活值&#xff09;无法建模层次空间关系&#xff08;旋转/平移等变换不敏感&#xff09;局部感受野限制全局特征整合 示例对比&#xff1a; # CNN最大池化示例…

如何下载AndroidStudio的依赖的 jar,arr文件到本地

一、通过jitpack.io 下载依赖库 若需要下载 com.github.xxxxx:yy-zzz:0.0.2 的 jar则 https://jitpack.io/com/github/xxxxx/yy-zzz/0.0.2/ 下会列出如下build.logyy-zzz-0.0.2.jaryy-zzz-0.0.2.pomyy-zzz-0.0.2.pom.md5yy-zzz-0.0.2.pom.sha1jar 的下载路径为https://jitpack…

Ubuntu中离线安装Docker

Ubuntu中离线安装Docker 前言 本教程将详细介绍如何在 Ubuntu 22.04 系统上&#xff0c;通过 .deb 包离线安装 Docker CE、Docker CE CLI 和 Docker Compose。 适用于无法访问互联网的环境。 准备工作 下载 .deb 包 在可以访问互联网的机器上&#xff0c;下载 Docker CE、…

【科研创新与智能化转型】AI智能体开发与大语言模型的本地化部署、优化技术

智能体&#xff08;Agent&#xff09;是指能够感知环境、自主决策并采取行动以实现特定目标的实体。它可以是一个软件程序、机器人或任何具备自主行为的系统。智能体的核心特征包括自主性、反应性、目标导向性和社会性。 智能体的主要特征 自主性&#xff1a;能够在没有外部干预…

【拒绝算法PUA】LeetCode 1287. 有序数组中出现次数超过25%的元素

系列文章目录 【拒绝算法PUA】0x00-位运算 【拒绝算法PUA】0x01- 区间比较技巧 【拒绝算法PUA】0x02- 区间合并技巧 【拒绝算法PUA】0x03 - LeetCode 排序类型刷题 【拒绝算法PUA】LeetCode每日一题系列刷题汇总-2025年持续刷新中 C刷题技巧总结&#xff1a; [温习C/C]0x04 刷…

6.2.4 基本的数据模型

文章目录 基本的数据模型 基本的数据模型 基本的数据模型包含层次模型&#xff0c;网状模型和关系模型。 层次模型&#xff1a;使用树型结构表示数据间联系。记录间的联系用指针实现&#xff0c;简单高效。但是只能表示1:n的联系&#xff0c;且对插入、删除的限制多。网状模型…