数据结构初阶(17)排序算法——非比较排序(计数排序·动图演示)、排序算法总结

 2.0 十大排序算法

2.5 非比较排序

之前学习的排序算法都是比较排序——借助比较大小,来实现排序。

非比较就是不借助比较大小,来实现排序。——小众的、局限的

非比较排序大致有这些:计数排序、桶排序、基数排序

桶排序、基数排序在实践中意义不大,面试也基本上不会考。

计数排序在实践中有所应用、校招也会有涉及。

2.5.1 计数排序

基本思想

计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。

动图演示

算法步骤

1. 统计相同元素出现次数。

2. 根据统计的结果将序列回收到原来的序列中。

图解演示。

适合:数据上界、下界差值小(<1000) ——数据范围集中的数组。

即不管数据大小, 只看数据集不集中。

不做绝对映射——即数据109不必要映射到数组的109位置, 只需要做相对映射。

数组的大小=最大值-最小值+1——找最值:遍历一遍(还是要比较)。

负数不是问题:min=-5 ——则-5-(-5)=0还是没问题。

反映射:5 + min = 105。

核心思想不是通过比较来达到有序的,找最值还是需要比较——遍历一遍O(N)。

代码实现
//计数排序
void CountSort(int* a, int n)
{//找最值——假设修正法int min = a[0], max = a[0];for (int i = 1; i < n; i++){//如果有更大——就更新一下最大值if (a[i] > max)max = a[i];if (a[i] < min)min = a[i];}//O(N)//0.计算数据范围int range = max - min + 1;//1.开辟计数数组int* count = (int*)malloc(sizeof(int) * range);if (count == NULL){perror("malloc fail");return;}memset(count, 0, sizeof(int) * range);//也可以在上面直接calloc——不过calloc的底层逻辑本来就是malloc + memset;//2.统计次数——遍历原数组——count数组相对位置处值++for (int i = 0; i < n; i++){// (1)统计次数的时候“减”min——“对应”下标位置的值++count[a[i] - min]++;}//3.排序——遍历count数组,将数据映射回原数组// i控制count遍历、j控制a遍历int j = 0;for (int i = 0; i < range; i++){//如果count对应位置不为0——为几走几次while (count[i]--)    //--k走k-1次;k--走k次{// 直接覆盖原数组// (2)还原的时候再把min“加”回来,用下标i加回min就是对应的a中的值a[j++] = i + min;}}
}

时间复杂度:arr数组大小N和count数组大小range当中,较大的那个。

  • O(N) 或者 O(range);
  • 或者直接O(N+range);

显然当范围range和数据量在同一量级时,计数排序就是最优排序。——O(N)

测试——100万个数据(空间不大,大概不到1MB = 2^20 ≈ 10^6,整型就是4MB)

void TestOP()
{srand(time(0));//要产生随机需要一个种子,否则随机是写死的伪随机const int N = 1000000;int* a1 = (int*)malloc(sizeof(int) * N);int* a2 = (int*)malloc(sizeof(int) * N);int* a3 = (int*)malloc(sizeof(int) * N);int* a4 = (int*)malloc(sizeof(int) * N);int* a5 = (int*)malloc(sizeof(int) * N);int* a6 = (int*)malloc(sizeof(int) * N);int* a7 = (int*)malloc(sizeof(int) * N);for (int i = 0; i < N; ++i){//a1[i] = rand() % 100;a1[i] = rand() % N;                    //产生100个数据——大小都在100万以内//a1[i] = rand();a2[i] = a1[i];a3[i] = a1[i];a4[i] = a1[i];a5[i] = a1[i];a6[i] = a1[i];a7[i] = a1[i];}int begin1 = clock();    //系统启动到执行到此的毫秒数//InsertSort(a1, N);int end1 = clock();      //系统启动到执行到此的毫秒数int begin7 = clock();//BubbleSort(a7, N);int end7 = clock();//int begin3 = clock();//SelectSort(a3, N);//int end3 = clock();//ShellSort(a2, N);int begin2 = clock();ShellSort(a2, N);int end2 = clock();int begin4 = clock();HeapSort(a4, N);//QuickSort1(a2, 0, N - 1);int end4 = clock();int begin5 = clock();QuickSort(a5, 0, N - 1);int end5 = clock();//PrintArray(a4, N);int begin6 = clock();MergeSortNonR(a6, N);int end6 = clock();int begin3 = clock();CountSort(a6, N);int end3 = clock();//printf("InsertSort:%d\n", end1 - begin1);//printf("BubbleSort:%d\n", end7 - begin7);printf("ShellSort:%d\n", end2 - begin2);//printf("SelectSort:%d\n", end3 - begin3);printf("HeapSort:%d\n", end4 - begin4);//printf("QuickSort1:%d\n", end4 - begin4);printf("QuickSort:%d\n", end5 - begin5);printf("MergeSort:%d\n", end6 - begin6);printf("CountSort:%d\n", end3 - begin3);free(a1);free(a2);free(a3);free(a4);free(a5);free(a6);free(a7);
}int main()
{//TestInsertSort();//TestBubbleSort();//TestShellSort();//TestSelectSort();//TestQuickSort();//TestMergeSort();//TestCountSort();TestOP();//MergeSortFile("sort.txt");return 0;
}

测试结果。


空间复杂度:

  • O(range)        ——数据越集中,空间复杂度越小
特性总结

计数排序的特性总结

特性

  1. 计数排序在数据范围集中时,效率很高(几乎最高),但是适用范围及场景有限。
  2. 时间复杂度:O( MAX(N,range) )
  3. 空间复杂度:O(范围)
  4. 稳定性:稳定

局限性

  • 数据要集中;
  • 只适合整型;
  • 有一定空间复杂度;(取决于数据的集中程度)

基数排序:先按个位排、再按十位排、再按百位排、……(只适合整型)

桶排序:把元素按区间分桶、桶内再排序,最后按桶顺序一次倒出来。(时间和空间都不占优)


实践中排序的对象大多都是结构体,所以计数排序在实践中的应用并不广泛。

而比较排序是通用的——只要能比较数据大小就能排——整型、浮点型、字符串、结构体……


排序的核心思想还是“比较”

  • 比较排序实用性广 && 大。
  • 非比较排序就是小众的 && 局限的,在特定情境下有自己的实践意义。

3. 排序算法复杂度及稳定性分析

稳定性:一个数组里面相同的数据,在排序前后的相对位置变不变

——只排序整型当然没有意义(两个5没差)
——故计数排序不考虑稳定性
——排序结构体就有意义了(两个5不一样)

稳定性的应用:

例1:同样分数的考试成绩,先交卷的同学,在排序时名字排在前面。——需要稳定排序

例2:同分数的同学,数学分数高的排名靠前——先按数学排序,再按总分排序。

最好不要靠背,要注重理解。

(1)三种O(N^2)的排序算法,只有选择排序不稳定,空间复杂度都是O(1)

时间处理上呈现等差数列——>O(N^2)
空间处理上不开额外空间——>O(1)

直接插入排序:相等的时候选择插入在后面,就稳定。


直接选择排序:乍一想感觉稳定,一些书上也说稳定,实际上不稳定。

选min的时候遇到相等(第二个1)就不更新min,可以保证1稳定。
但是在1和3交换后,就没办法保证3稳定。


冒泡排序:相邻比较,大的往后交换,相等就不换——稳定。

(2)一种O(?)的希尔排序,不稳定,空间复杂度O(1)

希尔排序:相同的数据,预排时可能分到不同的组,就不稳定。

(3)三种O(nlogn)的排序算法,只有归并稳定,只有堆排序空间复杂度O(1)

堆排序可以原地操作,不额外开空间
快速排序是递归,有空间复杂度的消耗的——要建立logN层栈帧
归并排序要建立一个辅助归并数组tmp

堆排序:举例说明不稳定——5 5 3,升序建好大堆,把第一个5(最大值)放到最后——不稳定。

快速排序:要把key交换到数组中间,比key小的在左边,比key大的在右边,和key相等的则在左边和右边都可以。

归并排序:归并的时候,取小的尾插到tmp数组,相等的时候优先尾插左区间的数据——稳定。
即:左 <= 右,就尾插左。

  • “三稳四不稳”
  • 只有快速排序、归并排序有空间复杂度的消耗
  • 只有直接插入排序、冒泡排序、无优化快速排序时间复杂度分最好最坏。
    (因为和数据是否有序有关)

整体看来,作为内排序,归并排序确实和其他几个一样有不错的效率,但是考虑到其必有O(N)的空间复杂度,相比之下还是快速排序更优。

4. 选择题练习


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

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

相关文章

VisualStudio2022调试Unity C#代码步骤

一.VS安装Unity开发组件按下图所示安装Unity开发组件二.附加Unity调试程序2.1 先将Unity进入Play模式2.2 VS选择附加Unity调试程序菜单2.3 选择附加的实例三.加入断点测试Update方法中成功进入断点

Zabbix【部署 01】Zabbix企业级分布式监控系统部署配置使用实例(在线安装及问题处理)程序安装+数据库初始+前端配置+服务启动+Web登录

Zabbix使用 1.下载 2.安装 2.1 程序安装 2.2 数据库初始化 2.3 前端配置 2.4 服务启动 3.Web登录 4.总结 安装说明: 本次安装为在线安装,使用数据库为PostgreSQL。 1.下载 由于是在线安装,这次不涉及离线安装包的下载,仅做参考用,点击跳转【下载页面】,下载说明: 版本…

爬机 验证服务器是否拒绝请求

当访问XX网站时返回 418 状态码时&#xff0c;说明服务器识别到了爬虫行为并拒绝了请求。这是网站的反爬机制在起作用&#xff0c;我们可以通过模拟浏览器行为来绕过基础反爬。import requestsurl https://cn.bing.com/# 模拟浏览器的完整请求头&#xff0c;包含更多浏览器标识…

GaussDB 数据库架构师修炼(十三)安全管理(3)-数据库审计

1 数据库审计作用数据库审计机制主要通过对SQL操作或其他操作记录审计日志的方式 &#xff0c;增强数据库系统对非法操作的追溯及举证能力 。高斯数据库提供两种审计特性 &#xff1a;传统审计 &#xff0c;统一审计。2 传统审计传统审计通过GUC参数配置需要对数据库的哪些操作…

C语言(11)—— 数组(超绝详细总结)

Hi&#xff01;冒险者&#x1f60e;&#xff0c;欢迎闯入 C 语言的奇幻异世界&#x1f30c;&#xff01; 我是 ankleless&#x1f9d1;‍&#x1f4bb;&#xff0c;和你一样的闯荡者&#xff5e; 这是我的冒险笔记打怪升级之路——C语言之路&#x1f4d6;&#xff0c;里面有踩过…

【AI生成+补充】高频 hql的面试问题 以及 具体sql

以下是高频HQL面试题及对应SQL示例&#xff0c;涵盖核心语法、优化技巧和典型场景&#xff0c;可直接用于面试准备&#xff1a; 一、基础操作与DDL 1. 创建分区表 & 动态插入分区 sql -- 创建外部分区表&#xff08;按日期分区&#xff09; CREATE EXTERNAL TABLE logs…

开源 Arkts 鸿蒙应用 开发(十七)通讯--http多文件下载

文章的目的为了记录使用Arkts 进行Harmony app 开发学习的经历。本职为嵌入式软件开发&#xff0c;公司安排开发app&#xff0c;临时学习&#xff0c;完成app的开发。开发流程和要点有些记忆模糊&#xff0c;赶紧记录&#xff0c;防止忘记。 相关链接&#xff1a; 开源 Arkts …

Cloudflare Tunnel 使用SAAS回源加速配置教程

在使用 Cloudflare Tunnel 时,通过“主域名+加速域名”的联动配置,既能隐藏内网 IP,又能优化访问速度。本文以实际部署场景为例(主域名 zhuyuming.dpdns.org、加速域名 jiasu.dpdns.org),带你一步步完成内网服务穿透(以 192.168.1.6:5555 网页服务为例),实操性强,可直…

C++实战

Ref deepwiki vuecruddllamma.cpp 目标 计划实现一个C项目&#xff0c;前端用vue&#xff0c;后端用C和llama.cpp。实现可以进行逻辑功能和AI推理。

dify 调用本地的 stable diffusion api生成图片的工作流搭建

Dify调用本地Stable Diffusion API的工作流搭建指南 核心架构 #mermaid-svg-ce029i4XFKrDzRgU {font-family:"trebuchet ms",verdana,arial,sans-serif;font-size:16px;fill:#333;}#mermaid-svg-ce029i4XFKrDzRgU .error-icon{fill:#552222;}#mermaid-svg-ce029i4XFK…

【Web后端】Django、flask及其场景——以构建系统原型为例

一、Django 和 Flask 简介 Django 是一个高级 Python Web 框架&#xff0c;提供了完整的“开箱即用”功能&#xff0c;包括 ORM、认证、管理后台等&#xff0c;便于快速开发安全且可维护的网站。Flask 是一个轻量级 Python Web 框架&#xff0c;核心功能比较简单&#xff0c;但…

飞算JavaAI:从智能调度到出行服务的全链路技术升级

免责声明&#xff1a;此文章所有内容都是实验测试数据 目录一、智慧交通核心场景的技术突破1.1 交通态势感知与智能预警系统1.2 公共交通智能调度系统1.3 一体化出行服务系统二、智慧交通系统效能升级实践2.1 交通数据中台构建结语&#xff1a;重新定义智慧交通技术边界一、智慧…

vscode的wsl环境,ESP32驱动0.96寸oled屏幕

注意大小写&#xff0c;wsl&#xff08;也就是linux环境&#xff09;严格区分大小写。有帮助记得订阅专栏点赞&#xff0c;当前不定期持续更新。 一、文件夹格式&#xff1a; project/ # 项目根目录 ├─ main/ # 主程序文件夹 │ ├─ mai…

CodeBuddy AI Coding 企业场景落地实践与思考

&#x1f449;目录1 引言2 诊断团队研发流程3 选择合适的 AI CODING 工具4 团队 AI 研发流程落地实践5 全面 CodeBuddy &#xff0c;深入 CodeBuddy6 诚邀共建在 AI 浪潮席卷全球的今天&#xff0c;AI CODING 已经不是企业研发团队的可选项&#xff0c;而是必选项。如果你是企业…

windows下hashcat使用gpu破解execl打开密码

需要的软件 1.hashcat &#xff1a;https://hashcat.net 2.john the ripper &#xff1a;https://www.openwall.com 获取execl加密文件的Hash PS G:\dl\john-1.9.0-jumbo-1-win64\john-1.9.0-jumbo-1-win64\run> python .\office2john.py .\test6.xlsx test6.xlsx:$office$*…

SpringCloud -- Nacos详细介绍

5. Nacos 5.1 Nacos介绍 Nacos 可以理解为微服务的“电话簿 遥控器”。它是阿里巴巴开源的一个核心工具&#xff0c;主要解决微服务架构中的两大问题&#xff1a; 5.1.1 服务注册与发现&#xff08;电话簿&#xff09; 服务注册&#xff1a;当某个微服务&#xff08;比如“订单…

【狂热算法篇】探寻图论幽径之SPFA算法:图论迷宫里的闪电寻径者(通俗易懂版)

​​​​​本篇带大家探究的是SPFA算法&#xff1b;从基本理解&#xff0c;画图分析展示&#xff0c;再到最后的代码实现&#xff0c;以及为何要这样实现代码&#xff0c;等一些细节问题做解释&#xff0c;相关题型应用&#xff0c;非常值得哟&#xff0c;尤其是刚入门的小白学…

webrtc网页一对一通话

基于flutter-webrtc-server做的更改&#xff0c;只使用网页实现语音和视频一对一通话&#xff0c;不支持多对多。 项目地址: https://github.com/chging/rtc-server

Java调用bat执行python脚本

1、问题概述&#xff1f;在windows环境中可以通过Java调用bat执行文件&#xff0c;从而调用python脚本&#xff0c;使用起来方便。2、实现方式&#xff1f;2.1、核心代码bat文件可以在任意位置//获取文件在项目中的文职 String batFilePathSystem.getProperty("user.dir&q…

JavaWeb 欢迎页设置详解

JavaWeb 欢迎页设置详解 欢迎页&#xff08;Welcome Page&#xff09;是用户访问 Web 应用根目录时自动展示的默认页面。在 JavaWeb 中有多种配置方式&#xff1a;一、配置方式 1. 通过 web.xml 配置&#xff08;传统方式&#xff09; <web-app><!-- 配置欢迎页列表 -…