01数据结构-归并排序和计数排序

01数据结构-归并排序和计数排序

  • 1.归并排序
    • 1.1归并排序概述
    • 1.2归并排序的执行流程
      • 1.2.1递(分裂)的过程
      • 1.2.2归(合并)的过程
    • 1.3归并排序的代码实现
  • 2.计数排序
    • 2.1算法思想
    • 2.2计数排序的改进
      • 2.2.1优化1
      • 2.2.2优化2

1.归并排序

1.1归并排序概述

归并排序,其排序的实现思想是先将所有的记录分开,然后两两合并,在合并的过程中将其排好序,最终得到一个完整的序列。由于使用到的递归思想,我个人认为也可以叫递归排序。归并排序非常适合大数据排序,大部分数据都在磁盘上,我们可以用归并排序拆分,我们拆成可以在内存中保存的n个有序区间,往回写到硬盘里,再进行合并这几个有序序列的时候工作量就变小了。

1.2归并排序的执行流程

1.不断地将当前序列平均分割成两个子序列:例如下面的序列,被分割成两个子序列,注意实际写代码的时候可能不会完全分割成两等份
在这里插入图片描述
2.然后继续将这些子序列分割成子序列,直到不能再分割位置。(序列中只剩下一个元素)
在这里插入图片描述
2.接下来,在不断的将两个子序列合并成一个有序序列:也就是说,刚刚是拆分,现在是合并。
在这里插入图片描述

合并的时候比较哪个序列的最小值更小就是真正的最小值,注意合并的7和8和上面分散的7和8是一个空间,我们是在原空间中排好序的,拆分完后我们沿路返回,只是方便大家看流程,在并的过程中我往下面画的,整个过程和树的DFS有点像,先处理完一边,再去处理另一边。

1.2.1递(分裂)的过程

在这里插入图片描述
我们设置两个left和right两个标志位,不断地分割序列,直到left==right,说明无法继续分割了,开始归回来,图中我没有画完全,只是做个展示。

1.2.2归(合并)的过程

在这里插入图片描述
最右边是我们要排序的序列的原空间,我们创建两个独立的空间用来存分裂后的序列,并创建两个指针指向两个序列空间中的最小值元素。第一次比较两个序列中指针指向的更小值为3,把它放入原序列的空间的第一号元素,在哪个空间中放的序列我们就把哪个空间的最小值指针往右边移动一位,另一个空间中的最小值元素指针不动,然后再次比较两个空间中指针指向的元素的较小值依次类推直到把其中某一个空间中的值全部放入了原空间中,再把另一个空间中的所有值排在后面即可。

1.3归并排序的代码实现

递进去拆分:

// 递归的分解table[left, right]区间
static void merge_loop(SortTable *table, int left, int right) {if (left >= right) {return;}int mid = (left + right) / 2;merge_loop(table, left, mid);merge_loop(table, mid + 1, right);// 区间拆分结束,合并两个子区间merge(table, left, mid, right);
}

合并过程:

// merge合并过程
static void merge(SortTable *table, int left, int mid, int right) {int n1 = mid - left + 1;        // 左边区间的个数int n2 = right - mid;           // 右边区间的个数// 分配aux1和aux2,将已经有序的左区间和已经有序的右区间 初始化临时区域Element *aux1 = malloc(sizeof(Element) * n1);if (aux1 == NULL) {return;}Element *aux2 = malloc(sizeof(Element) * n2);if (aux2 == NULL) {free(aux1);return;}for (int i = 0; i < n1; i++) {aux1[i] = table->data[left + i];}for (int i = 0; i < n2; ++i) {aux2[i] = table->data[mid + 1 + i];}// 将临时的有序空间aux1和aux2进行归并int i = 0;          // 标记aux1区间待查找的位置int j = 0;          // 标记aux2区间待查找的位置int k = left;       // 标记原空间存放结果的区域位置while (i < n1 && j < n2) {if (aux1[i].key <= aux2[j].key) {table->data[k] = aux1[i];++i;} else if (aux1[i].key > aux2[j].key) {table->data[k] = aux2[j];++j;}k++;}// 判断究竟是aux1还是aux2区域遍历结束while (i < n1) {table->data[k++] = aux1[i++];}while (j < n2) {table->data[k++] = aux2[j++];}free(aux1);free(aux2);
}

注意这里初始化的时候要加上序列左边的基地址。

接口调用:

/* 归并排序:从上往下,从下往上两个过程* 从上往下的过程:*  a. 分解 -- 将当前区间一分为二*  b. 求解 -- 递归对两个子区间a[low...mid] 和 a[mid+1...high]进行归并排序*/
void mergeSort(SortTable *table) {merge_loop(table, 0, table->length - 1);
}

最后来测一下:

#include "mergeSort.h"int main() {int n = 10000;SortTable *table = generateRandomArray(n, 0, n + 5000);testSort("Merge Sort", mergeSort, table);releaseSortTable(table);return 0;
}

结果:

D:\work\DataStruct\cmake-build-debug\04_Sort\MergeSort.exe
Merge Sort cost time: 0.002000s.进程已结束,退出代码为 0

时间复杂度也是接近O(nlogn)。

2.计数排序

计数排序(Counting Sort)是一种针对于特定范围之间的整数进行排序的算法。它通过统计给定数组中不同元素的数量(类似于哈希映射),然后对映射后的数组进行排序输出即可。(计数排序在某些情况下比快速排序还要快)

2.1算法思想

我们以数组 [1,4,1,2,5,2,4,1,8] 为例进行说明。

第一步:建立一个初始化为 0 ,⻓度为 9 (原始数组中的最大值 8 加 1) 的数组 count[]

第二步:遍历数组[1,4,1,2,5,2,4,1,8],访问第一个元素1,然后将数组标为1的元素加1,表示当前1出现了1此,即count[1]=1;

依次遍历,对count进行统计。
在这里插入图片描述

2.2计数排序的改进

  • 无法对负数进行排序
  • 极其浪费空间
  • 是一个不稳定排序

2.2.1优化1

只要不再以数列的[最大值+1]作为统计数组的长度,而是以数列[最大值-最小值+1]作为统计数组的长度即可。数列最小值作为一个偏移量,用于计算整数在统计数组中的下表

2.2.2优化2

为了使计数排序稳定,我们从统计数组的第2个元素开始,每一个元素都加上前面元素之和,相加的目的是让统计数组存储的元素值,等于对应整数的最终排序位置的序号,遍历的时候从后向前遍历原数组(在填充输出数组时)来保证稳定性。

计数排序了解一下即可,还有一些排序比如选择排序,桶排序我就不一一写了,大家可以自己去看,大概先写这些吧,今天的博客就先写到这,谢谢您的观看。

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

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

相关文章

SQL注入2----(sql注入数据类型分类)

一.前言本章节我们来讲解一下sql注入的分类&#xff0c;主要分为四类&#xff0c;数字型、字符型、搜索型、xx型。二.数字型数字型注入的时候&#xff0c;是不需要考虑单\双引号闭合问题的&#xff0c;因为sql语句中的数字是不需要用引号括起来的&#xff0c;如下mysql> sel…

Elasticsearch Rails 实战全指南(elasticsearch-rails / elasticsearch-model)

一、背景与生态总览 elasticsearch-rails&#xff1a;面向 Rails 的“伴生库”&#xff0c;为 Rails 项目带来 Rake 任务、日志埋点、模板等特性。elasticsearch-model&#xff1a;把 ES 能力“混入”到 Ruby 模型&#xff08;ActiveRecord/Mongoid&#xff09;&#xff0c;提供…

第三阶段数据库-2:数据库中的sql语句

1_数据库操作&#xff08;1&#xff09;注释&#xff1a;-- 单行注释 /**/ 多行注释&#xff08;2&#xff09;创建数据库&#xff1a;create database 数据库名-- create database 数据库名 create database db_first;(3&#xff09;查询数据库&#xff1a;if exsists(select…

python中的filter函数

目录 定义与参数说明 特点 使用场景 常用操作 筛选偶数 去除空字符串 筛选正数 筛选字典 配合集合与元组 注意事项 定义与参数说明 filter函数是Python内置的高阶函数之一&#xff0c;用于筛选可迭代对象中的元素&#xff0c;根据返回值的布尔结果&#xff08;True 或…

BERT(Bidirectional Encoder Representations from Transformers)模型详解

一、BERT 简介BERT&#xff08;Bidirectional Encoder Representations from Transformers&#xff09;是由 Google 在 2018 年提出的一种预训练语言表示模型。它基于 Transformer 编码器结构&#xff0c;首次提出了 双向上下文建模 的方法&#xff0c;大幅度提升了自然语言处理…

【开题答辩全过程】以 基于Springboot+微信小程序的网上家教预约系统的设计与实现-开题为例,包含答辩的问题和答案

个人简介&#xff1a;一名14年经验的资深毕设内行人&#xff0c;语言擅长Java、php、微信小程序、Python、Golang、安卓Android等开发项目包括大数据、深度学习、网站、小程序、安卓、算法。平常会做一些项目定制化开发、代码讲解、答辩教学、文档编写、也懂一些降重方面的技巧…

课小悦系列智能耳机上市,用硬核科技为教育赋能

在人工智能与教育深度融合的浪潮中&#xff0c;深圳课小悦科技有限公司以“智慧教育专家”的姿态崭露头角。这家深耕智能教育硬件的创新企业&#xff0c;于2025年8月正式推出革命性产品H360PRO系列教考耳机&#xff0c;为语言学习场景提供颠覆性解决方案。创新基因&#xff1a;…

[react] class Component and function Component

我对react的用法理解还一直停留在多年以前&#xff0c;说明这段时间我没有更新react的知识。我大脑中记得还是使用Class Component this.setState&#xff0c;可是今天看了看react的文档&#xff0c;发现怎么不一样了&#xff0c;用的都是function useState的方式了。你知道这…

以太坊智能合约地址派生方式:EOA、CREATE 和 CREATE2

1. 引言 在以太坊上&#xff0c;智能合约可以通过以下三种方式之一进行部署&#xff1a; 1&#xff09;由外部账户&#xff08;Externally Owned Account, EOA&#xff09;发起交易&#xff0c;其中 to 字段设为 null&#xff0c;而 data 字段包含合约的初始化代码。2&#x…

基于RISC-V架构的国产MCU在eVTOL领域的应用研究与挑战分析

摘要电动垂直起降飞行器&#xff08;eVTOL&#xff09;作为未来城市空中交通的重要组成部分&#xff0c;对嵌入式控制系统的性能、可靠性和安全性提出了极高的要求。RISC-V作为一种新兴的开源指令集架构&#xff0c;为国产微控制器&#xff08;MCU&#xff09;的研发和应用带来…

深度学习中的“集体智慧”:Dropout技术详解——不仅是防止过拟合,更是模型集成的革命

引言&#xff1a;从“过拟合”的噩梦说起 在训练深度学习模型时&#xff0c;我们最常遇到也最头疼的问题就是过拟合&#xff08;Overfitting&#xff09;。 想象一下&#xff0c;你是一位正在备考的学生&#xff1a; 欠拟合&#xff1a;你根本没学进去&#xff0c;所有题都做错…

在JavaScript中,比较两个数组是否有相同元素(交集)的常用方法

方法1&#xff1a;使用 some() includes()&#xff08;适合小数组&#xff09;function haveCommonElements(arr1, arr2) {return arr1.some(item > arr2.includes(item)); }// 使用示例 const arrA [1, 2, 3]; const arrB [3, 4, 5]; console.log(haveCommonElements(ar…

心路历程-Linux的系统破解详细解说

CentOS7系统密码破解 密码破解是分两种情况的&#xff1b;一种是在系统的界面内&#xff0c;一种就是不在系统的页面&#xff1b; 今天我们就来聊聊这个系统破解的话题&#xff1b; 1.为什么需要破解密码&#xff1f;–>那当然是忘记了密码&#xff1b;需从新设置密码 2.但是…

IDE和AHCI硬盘模式有什么区别

IDE&#xff08;Integrated Drive Electronics&#xff09;和 AHCI&#xff08;Advanced Host Controller Interface&#xff09;是硬盘控制器的工作模式&#xff0c;主要区别在于性能、功能兼容性以及对现代存储设备的支持程度。以下是详细对比和分析&#xff1a;一、本质区别…

【密码学实战】密码实现安全测试基础篇 . KAT(已知答案测试)技术解析与实践

KAT 测试技术解析 在密码算法的安全性验证体系中&#xff0c;Known Answer Test&#xff08;KAT&#xff0c;已知答案测试&#xff09;是一项基础且关键的技术。它通过 “已知输入 - 预期输出” 的确定性验证逻辑&#xff0c;为密码算法实现的正确性、合规性提供核心保障&…

如何用Redis作为消息队列

说明&#xff1a;以前背八股文&#xff0c;早就知道 Redis 可以作为消息队列&#xff0c;本文介绍如何实现用 Redis 作为消息队列。 介绍 这里直接介绍 yudao 框架中的实现。yudao 是一套现成的开源系统框架&#xff0c;里面集成了许多基础功能&#xff0c;我们可以在这基础上…

解决 uniapp 修改index.html文件不生效的问题

业务场景&#xff1a;需要在H5网站设置追踪用户行为&#xff08;即埋点&#xff09;的script代码。 问题&#xff1a;无论如何修改根目录下的index.html文件都不会生效 问题原因&#xff1a;在 manifest.json 文件中有个【web配置】—>【index.html模版路径】&#xff0c;…

C语言第十一章内存在数据中的存储

一.整数在内存中的存储在计算机内存中&#xff0c;所有的数字都是以二进制来存储的。整数也不例外&#xff0c;在计算机内存中&#xff0c;整数往往以补码的形式来存储数据。这是为什么呢&#xff1f;在早期计算机表示整数时&#xff0c;最高位为符号位。但是0却有两种表示形式…

K8s部署dashboard平台和基本使用

Kubernetes 的默认 Dashboard 主要用于基本的资源查看与管理,如查看 Pod、Service 等资源的状态,进行简单的创建、删除操作 。然而,在企业级复杂场景下,其功能显得较为局限。 与之相比,开源的 Kubernetes Dashboard 增强版工具 ——Dashboard UI ,为用户带来了更强大的功…

JavaEE进阶-文件操作与IO流核心指南

文章目录JavaEE进阶文件操作与IO流核心指南前言&#xff1a;为什么需要文件操作&#xff1f;一、java.io.File 类的基本用法1.1 文件路径1.2 常用方法示例获取文件信息创建和删除文件目录操作文件重命名和移动二、IO流的基本概念2.1 核心困境&#xff1a;字节流 vs. 字符流字节…