排序算法——比较类排序算法讲解以及c++实现

2023-11-16

首先我先抛一个老哥的博客,我是看着他的博客来学习理解

地址:https://www.cnblogs.com/onepixel/p/7674659.html

 

首先说一下排序算法分为2类:一类是比较类排序算法,另一类是非比较类排序,这里主要讲常用的比较类排序算法

包括插入排序,选择排序,冒泡排序,希尔排序,快速排序,归并排序,堆排序

先讲一下各个算法的复杂度

时间复杂度方面,快速排序,归并排序,堆排序的是最好的,一般比较常用。

 

1.插入排序(时间复杂度o(n2))

它的工作原理是通过构建有序序列,对于未排序数据,在已排序序列中从后向前扫描,找到相应位置并插入。

通俗的讲就是从第二个开始依次跟之前的元素做比较,如果比前一个元素小则交换位置,直到成为第一个元素或者前一个元素小于该元素。

附一下c++代码:

#include <iostream>
using namespace std;
int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    for(int i=1;i<num;i++){
        int j=i;
        while(j>=1){
            if(nums[j]<nums[j-1]){
                int temp=nums[j-1];
                nums[j-1]=nums[j];
                nums[j]=temp;
            }
            j--;
        }
    }
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

2. 选择排序(时间复杂度o(n2))

它的工作原理:首先在未排序序列中找到最小(大)元素,存放到排序序列的起始位置,然后,再从剩余未排序元素中继续寻找最小(大)元素,然后放到已排序序列的末尾。以此类推,直到所有元素均排序完毕。 

通俗讲就是在所有元素中找到最小(大)的与下标为0的元素交换,然后再在剩下的所有元素中重复上述操作即可。

附一下c++代码:

#include <iostream>
using namespace std;

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    for(int i=0;i<num;i++){
        for(int j=i+1;j<num;j++){
            if(nums[j]<nums[i]){
                int temp=nums[i];
                nums[i]=nums[j];
                nums[j]=temp;
            }
        }
    }
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

3. 冒泡排序(时间复杂度o(n2))

它重复地走访过要排序的数列,一次比较两个元素,如果它们的顺序错误就把它们交换过来。走访数列的工作是重复地进行直到没有再需要交换,也就是说该数列已经排序完成。这个算法的名字由来是因为越小的元素会经由交换慢慢“浮”到数列的顶端。 

每次都是从下标为0开始到最后一个元素,第一次会把最大(小)的元素放到最后一个位置,依次类推即可。

附上c++ 代码:

#include <iostream>
using namespace std;

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    for(int i=0;i<num;i++){
        for(int j=0;j<num-1-i;j++){
            if(nums[j]>nums[j+1]){
                int temp=nums[j+1];
                nums[j+1]=nums[j];
                nums[j]=temp;
            }
        }
    }
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

4.希尔排序(时间复杂度o(n2))

  • 选择一个增量序列t1,t2,…,tk,其中ti>tj,tk=1;
  • 按增量序列个数k,对序列进行k 趟排序;
  • 每趟排序,根据对应的增量ti,将待排序列分割成若干长度为m 的子序列,分别对各子表进行直接插入排序。仅增量因子为1 时,整个序列作为一个表来处理,表长度即为整个序列的长度。

附一下c++代码:

#include <iostream>
#include <queue>
using namespace std;
void shellSort(int arr[],int n);

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    //希尔排序
    shellSort(nums,num);
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

void shellSort(int arr[],int n) {
    for (int gap = n/ 2; gap > 0; gap = gap / 2) {
        // 注意:这里和动图演示的不一样,动图是分组执行,实际操作是多个分组交替执行
        for (int i = gap; i < n; i++) {
            int j = i;
            int current = arr[i];
            while (j - gap >= 0 && current < arr[j - gap]) {
                 arr[j] = arr[j - gap];
                 j = j - gap;
            }
            arr[j] = current;
        }
    }
}

5.快速排序(时间复杂度o(nlogn))

快速排序的基本思想:选择其中的一个元素(一般选择第一个元素或者最后一个)将通过一趟排序将待排记录分隔成独立的两部分,其中一部分记录的关键字均比另一部分的关键字小,则可分别对这两部分记录继续进行排序,以达到整个序列有序。

附上c++代码

#include <iostream>
using namespace std;
void quicksort(int[],int begin,int end);
int partition(int[],int begin,int end);

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    //快速排序调用
    quicksort(nums,0,num-1);
    
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

//快速排序
void quicksort(int arr[],int begin,int end){
    if(end<=begin) return;
    int povit=partition(arr,begin,end);
    quicksort(arr,begin+1,end);
    quicksort(arr,begin,end-1);
}
//找关键元素
int partition(int arr[],int begin,int end){
    //pivot: 标杆 标杆位置, counter: 小于pivot的元素的个数
     int pivot=end;
     int counter=begin;
     for(int i=begin;i<end;i++){
         if(arr[i]<arr[pivot]){
             int temp=arr[counter];
             arr[counter]=arr[i];
             arr[i]=temp;
             counter++;
         }
     }
     int temp=arr[pivot];
     arr[pivot]=arr[counter];
     arr[counter]=temp;
     return counter;
}

6.归并排序(时间复杂度o(nlogn))

归并排序的思想是将待排序所有元素一分为二,然后两部分内部继续归并排序,直到分成的待排序元素个数小于等于2再进行归并 处理,两个 排序好的元素列表再进行合并,最后得到排序结果。

附一下c++代码

#include <iostream>
using namespace std;
void mergesort(int[],int left,int right);
void merge(int[],int left,int mid,int right);

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    //归并排序调用
    mergesort(nums,0,num-1);
    
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}

void mergesort(int arr[],int left,int right){
    if(right<=left) return ;
    int mid=(left+right)/2;
    mergesort(arr,left,mid);
    mergesort(arr,mid+1,right);
    merge(arr,left,mid,right);
}

void merge(int arr[],int left,int mid,int right){
    int temp[right-left+1];
    int i=left,j=mid+1,k=0;
    while(i<=mid&&j<=right){
        temp[k++]=arr[i]<=arr[j]?arr[i++]:arr[j++];
    }
    while(i<=mid) temp[k++]=arr[i++];
    while(j<=right) temp[k++]=arr[j++];
    for(int h=0;h<right-left+1;h++){
        arr[left+h]=temp[h];
    }
}

7.堆排序(时间复杂度o(nlogn))

堆排序(Heapsort)是指利用堆这种数据结构所设计的一种排序算法。堆积是一个近似完全二叉树的结构,并同时满足堆积的性质:即子结点的键值或索引总是小于(或者大于)它的父节点。在c++中使用优先队列进行存储然后进行输出即可完成排序, 排序工作在内部完成的。

附一下c++代码即可:

#include <iostream>
#include <queue>
using namespace std;

void heapsort(int[],int length);

int main() {
    int num;
    cin>>num;
    int nums[num];
    for(int i=0;i<num;i++)
        cin>>nums[i];
    //堆排序
    heapsort(nums,num);
    
    for(int i=0;i<num;i++){
        cout  << nums[i] <<" ";
    }
	return 0;
}
void heapsort(int arr[],int length){
    priority_queue<int, std::vector<int>,greater<int> > q ;
    
    for(int i=0;i<length;i++){
        q.push(arr[i]);
    }
    for(int i=0;i<length;i++){
        arr[i] =q.top();
        q.pop();
    }
}

 

 

 

最后总结一下子:

这些算法里面有复杂的,也有比较容易理解的,主要学习是先理解,看懂代码,然后自己写出代码。

如果在应用过程中追求效率的话,首选归并排序、快速排序、堆排序(空间复杂度低)来解决问题,这几种算法比较难理解,可

以多背多写达到一个灵活应用的水平。

如果不追求效率的话,基本的排序就可以完成,选择排序、插入排序、冒泡排序,基本异曲同工,比较容易理解,按理解写出来

即可。

本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系:hwhale#tublm.com(使用前将#替换为@)

排序算法——比较类排序算法讲解以及c++实现 的相关文章

  • 从 C# 调用非托管 dll。拿2

    我编写了一个 C 程序 它调用一个 C DLL 将命令行参数回显到文件中 当使用 rundll32 命令调用 c 时 它显示命令行参数没有问题 但是当从 c 内部调用它时 它不会显示 我问了这个问题 https stackoverflow
  • 如何拦截 .Net 中第三方库对非虚拟方法的调用?

    我认为我需要的是 net 人们称之为 透明动态代理 的东西 但到目前为止我所看到的所有实现 Castle DynamicProxy Spring NET AOP 等 都要求我至少执行以下操作之一 将拦截的方法声明为虚拟方法 包装类并创建包装
  • 即使我没有#include ,为什么仍然可以使用 std::max 和 std::min ?

    include
  • 将数据集导出到 EXCEL

    我使用以下代码将数据库表中的字段导出到 Excel 中 我想要做的是能够编写一条 SQL 语句从多个表中检索字段并将其导出到 Excel 中 这段代码只允许我导出一张表 另外 如何显示保存提示对话框 示例代码将不胜感激 非常感谢 prote
  • 使用 getopt_long (C++) 如何为两个需要参数编写长选项和短选项?

    include
  • 如何使用movntdqa避免缓存污染?

    我正在尝试编写一个 memcpy 函数 该函数不会将源内存加载到 CPU 缓存中 目的是避免缓存污染 下面的 memcpy 函数可以工作 但会像标准 memcpy 一样污染缓存 我正在使用带有 Visual C 2008 Express 的
  • Reflection.Emit 中的短格式操作码错误

    我正在制作一种与以下非常相似的小语言hlsl但仅支持像素着色器 该语言使用reflection emit构建实现相同功能的 NET 程序集 我目前正在测试分支指令的实现if在我的一个单元测试中 一个大的if与内if elses 失败并显示以
  • 尝试将元素推入向量

    在头文件 我没有编写 中 已经定义了一个结构体 如下所示 struct MemoryMessage public boost counted base public FastAlloc explicit MemoryMessage Memo
  • 在 C 程序中追踪数组越界访问/写入的推荐方法

    考虑用 C 语言编写一些不太明显的算法的实现 例如 让它成为递归快速排序 我在 K N King 的 C 编程 现代方法 第二版 书中找到了它 可以从here http knking com books c2 programs qsort
  • 使用 Thread.Sleep() 时,异步编程如何与线程一起工作?

    假设 前言 在之前的问题中 我们注意到Thread Sleep阻塞线程参见 什么时候使用Task Delay 什么时候使用Thread Sleep https stackoverflow com questions 20082221 whe
  • 使用 C 创建立体声正弦波

    我正在尝试用 C 创建立体声正弦 WAV 并且可能有不同的 可能是空白的 左声道和右声道 使用此函数为每个通道生成一个音调 int16 t create tone float frequency float amplitude float
  • Xamarin 无法从异步获取实例

    我编写了一个通过蓝牙连接到 ESP32 的 Xamarin Forms 应用程序 现在我想从 MainPage xaml 页面的 CustomControl JoystickControl 获取值 我已经这样尝试过了 MainPage xa
  • NHibernate 中具有不同类型答案的问题

    我正在尝试找到一个问卷问题的简洁解决方案 假设我有一个Questionnaire类有一个集合Answers e g public class Questionnaire public virtual ISet
  • 专家 C#/.Net/WPF 开发人员应该了解哪些知识? [关闭]

    就目前情况而言 这个问题不太适合我们的问答形式 我们希望答案得到事实 参考资料或专业知识的支持 但这个问题可能会引发辩论 争论 民意调查或扩展讨论 如果您觉得这个问题可以改进并可能重新开放 访问帮助中心 help reopen questi
  • 在 C# 中加密并在 Flex 中解密

    我需要解密 Flex 中的一些数据 这些数据是用 C 加密并写入文件的 为了简单起见 我选择使用 as3crypto As3 库和 Bruce Schneier C 库 AS3 as3加密链接 http code google com p
  • 我可以在C中直接比较int和size_t吗?

    我可以比较一个int and a size t像这样的变量 int i 1 size t y 2 if i y Do something 或者我必须输入其中之一 只要满足以下条件 它就是安全的int为零或正数 如果它是负数 并且size t
  • 在 C# 中将 ulong 映射到 long ?

    我正在尝试将 ulong 映射到 long 反之亦然 将 uint 映射到 int 反之亦然 如下所示 为了将值保存在具有签名类型的 MS SQL 数据库中仅限整数和大整数 我这样做是因为我必须检查 在数据库中 一个数字 uint ulon
  • 父窗体中的居中消息框[重复]

    这个问题在这里已经有答案了 有没有一种简单的方法可以在 net 2 0中将MessageBox居中于父窗体中 我在 C 中确实需要这个并发现中心消息框 C http bytes com topic c sharp answers 26712
  • 当另一个进程使用 std::fstream 写入文件时从文件读取[重复]

    这个问题在这里已经有答案了 我需要从文件中逐行读取 它是由 std getline 完成的 另一个进程的问题是一直向其附加数据 然后我需要读取新行 例如 文件一开始包含10行 我的程序读取了10行 那么我的程序应该等待 过了一会儿 另一个进
  • 你将如何开始自动化我的工作? - 第2部分

    后续这个问题 https stackoverflow com questions 2796128 how would you start automating my job 在经历了第一波进货 9 小时的复制 粘贴 后 我现在相信我已经满足

随机推荐

  • Vivado的一些tcl命令记录(待补充)

    1 Report Clock Networks report clock networks name network 1 2 分析设计中逻辑级数的分布 report design analysis logic level distribut
  • NLP(自然语言处理)是什么?

    NLP基本概念 自然语言处理 Natural Language Processing NLP 是以语言为对象 利用计算机技术来分析 理解和处理自然语言的一门学科 即把计算机作为语言研究的强大工具 在计算机的支持下对语言信息进行定量化的研究
  • simplest-jpa v1.2.0如何优雅实现多租户

    开始使用 simplest详细文档 simplest jpa 使用多租户需要 2 个步骤 在属性中配置对应租户表和列 配置 TenantFactory 注入租户数据源 TenantFactory 是用于生产租户 ID 的 或者说是用于获取当
  • idea 内存不足 low memory 彻底解决

    1 在IDE中 帮助 help gt 编辑自定义vm配置 idea64 exe vmoptions文件 修改 Xmx2048m Xms2048m 增加根据自己的系统内存 此时重启idea 仍然报内存不足 提示提高内存 通过idea log发
  • Loader Runner 课程笔记(一)录制设置和压测

    1 录制前设置 1 创建脚本 新建单协议脚本 选择Web协议 创建 LR11只支持WIN7系统 浏览器IE8 9和低版本的火狐 24 0或36 0 高版本IE可以卸载装IE8或9 不支持谷歌 LR自带火狐路径HP LoadRunner bi
  • 关于ECC-Elgamal同态加密

    关于ECC Elgamal同态加密 1 什么是ECC elliptic curve 1 有限域 首先我们要知道椭圆曲线加密是在有限域进行加密的 对于无限域上的加密我没有了解过 在椭圆曲线 加密上有限域分为 1 GF p 素数域2 GF 2
  • Python 爬虫案例

    一 用cookie池模拟登录 在网络请求交互中 为了维持用户的登录状态 引入了cookie的概念 当用户第一次登录某个网站时 网站服务器会返回维持登录状态需要用到的信息 这些信息就称为cookie 浏览器会将cookie信息保存在本地计算机
  • Intellij IDEA快速实现Docker镜像部署

    1 Docker开启远程访问 root izwz9eftauv7x69f5jvi96z docker vim lib systemd system docker service 修改ExecStart这行 ExecStart usr bin
  • python中各种文件类型的读写

    本文汇总了在python中各种类型文件的读取和写入 包含文本 图像 表格 log文件 pickle文件 npy文件 npz文件等 文本类型 txt文件 json文件 yaml文件 图像类型 使用skimage PIL opencv imag
  • Java解决线程安全问题

    文章目录 背景 1 线程安全问题 1 1 什么是线程安全 1 2 产生的原因 1 3 实例 买票超卖问题 1 4 如何确定是否存在线程安全问题 2 如何解决线程安全问题 2 1 不可变 Immutable 2 2 变量私有化 2 2 1 栈
  • 数据库--商品 表的设计

    目录 商品分类表 商品品牌表 商品分类表 tb item cat 树状结构 CREATE TABLE tb item cat id bigint 20 NOT NULL AUTO INCREMENT COMMENT 类目ID parent
  • GBDT调库代码示例

    二 使用GBDT预测新能源汽车充电桩的故障检测问题 55分 请你用训练数据构建相应的模型 并将模型进行保存 import matplotlib pyplot as plt 正常显示中文及字符 plt rcParams font family
  • python中返回上一步操作_通过实例解析Python文件操作实现步骤

    当程序运行时 变量是保存数据的好方法 但变量 序列以及对象中存储的数据是暂时的 程序结束后就会丢失 如果希望程序结束后数据仍然保持 就需要将数据保存到文件中 Python 提供了内置的文件对象 以及对文件 目录进行操作的内置模块 通过这些技
  • Nginx启动只有master进程而没有worker进程

    大致按照下面文章的提示进行排查 https blog csdn net sinat 37729104 article details 102662475 https blog csdn net qt10086 article details
  • docker配置java环境和mysql数据库

    1 安装docker 1 安装命令 yum install docker 有提示直接y确认 2 设置开机自动启动 service docker start 3 查看版本 docker version 4 修改docker仓库地址 命令 vi
  • stm32定时器时钟源时钟选择,重点是外部时钟源1模式的理解

    stm32定时器时钟源时钟选择 stm32定时器时钟源时钟选择 有意义的参考 TI与ITRX的区别参考 https blog csdn net gtkknd article details 39292517 解析参考 https blog
  • Jenkins持续集成-实现自动向gitlab拉取代码并构建

    Jenkins服务操作 1 选择系统管理 gt 插件管理 gt 可选插件 gt 下载 gitlab 插件 2 选择新建任务 gt 构建 一个自由项目 2 填写相应的gitlab仓库地址和密钥信息 3 在 构建触发器 gt 选择 Buil w
  • [Java] 方法签名(method signature)

    方法头指定修饰符 例如static 返回值类型 方法名 和形式参数 方法头中定义的变量称为形参 形式参数 formal parameter 或 parameter 形参如同占位符 当方法被调用时 传递一个值给形参 此值称为实参 实际参数 a
  • python使用 pyinstaller -F -w file报PermissionError问题

    python使用 pyinstaller F w file报PermissionError问题 根据自己的情况 该报错重新安装pyinstaller 或者重启一下pycharm可以解决一次该问题 但是如果第二次打包就会报该问题 但是 经过验
  • 排序算法——比较类排序算法讲解以及c++实现

    首先我先抛一个老哥的博客 我是看着他的博客来学习理解 地址 https www cnblogs com onepixel p 7674659 html 首先说一下排序算法分为2类 一类是比较类排序算法 另一类是非比较类排序 这里主要讲常用的