数据结构排序——计数排序和排序总结(附上912. 排序数组讲解)

2024-01-14 12:36

本文主要是介绍数据结构排序——计数排序和排序总结(附上912. 排序数组讲解),希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

数据结构排序——计数排序和排序总结

现在常见算法排序都已讲解完成,今天就再讲个计数排序。再总结一下
请添加图片描述


文章目录

  • 1.计数排序
  • 2.排序总结
  • 3.排序oj(排序数组)
    • 题目详情
    • 代码
    • 思路


1.计数排序

计数排序是一种非基于比较的排序算法,它通过统计数组中每个元素出现的次数,然后根据元素的值和出现次数重新构造数组,从而实现排序。计数排序适用于元素范围比较小元素非负的情况

步骤:

  1. 找出待排序的数组中最大和最小的元素:min和max
  2. 统计数组中每个值为 i 的元素出现的次数,存入新建数组 C 的第 i-min 项(c初始化时都是0),每遇到一次,对应下标上的数就++
  3. 反向填充目标数组:利用新建的数组把数据覆盖回去

时间复杂度:O(n + range)

void CountSort(int* a, int n)
{//先找最大最小,确定范围int max = a[0], min = a[0];for (int i = 1; i < n; i++){if (a[i] > max){max = a[i];}if (a[i] < min){min = a[i];}}int range = max - min + 1;int* count= (int*)calloc(sizeof(int) * range);if (count == NULL){perror("malloc fail");return;}//开始想count中累加了for (int i = 0; i < n; i++){count[a[i] - min]++;}//赋值覆盖int a_index = 0;for (int i = 0; i < range; i++){for (int j = 0; j < count[i]; j++){a[a_index] = i + min;a_index++;}}
}int main()
{int a[] = { 2,4,1,7,9 };CountSort(a, 5);for (int i = 0; i < 5; i++){printf("%d ", a[i]);}return 0;
}

2.排序总结

排序算法时间复杂度空间复杂度稳定性
直接插入排序O(N^2)O(1)稳定
希尔排序O(N^1.3)O(logN)不稳定
选择排序O(N^2)O(N)不稳定
堆排序O(N*logN)O(N)不稳定
冒泡排序O(N^2)O(1)稳定
快速排序O(N*logN)O(logN)不稳定
归并排序O(N*logN)O(N)稳定

不稳定的情况之一:

  1. 希尔:根据gap分组不在一个组
  2. 选择:3 3 1 1…
  3. 堆排序:向下调整过程
  4. 快排:相同的数字其中一个在keyi的位置

3.排序oj(排序数组)

题目详情

912. 排序数组 - 力扣(LeetCode)

请添加图片描述

代码

void Swap(int* x, int* y)
{int tmp = *x;*x = *y;*y = tmp;
}int GetMid(int* a,int left, int right)//找中间的
{// a[left]      a[mid]           a[right]int mid = left+(rand()%(right-left));if (a[left] < a[mid]){if (a[mid] < a[right]){return mid;}else if (a[left] > a[right])  // mid是最大值{return left;}else{return right;}}else // a[left] > a[mid]{if (a[left] < a[right]){return left;}else if (a[mid] < a[right]){return right;}else{return mid;}}
}void QuickSort(int* a, int left, int right)
{if (left >= right){return;}int begin = left;int end = right;int mid = GetMid(a, left, right);Swap(&a[mid], &a[left]);int cur = left + 1;int key = a[left];//储存一下,后面比较来用,用a[left]会被替代while (cur <= right){if (a[cur] < key){Swap(&a[cur], &a[left]);cur++;left++;}else if (a[cur] == key){cur++;}else{Swap(&a[cur], &a[right]);right--;}}QuickSort(a, begin, left - 1);QuickSort(a, right + 1, end);
}int* sortArray(int* nums, int numsSize, int* returnSize) {srand(time(0));QuickSort(nums,0,numsSize-1);*returnSize=numsSize;return nums;
}

请添加图片描述

  1. Swap函数: 这是一个用于交换两个整数值的简单函数。
  2. GetMid函数: 用于在数组中找到三个位置(左、中、右)的元素,从而选取合适的中间值。它通过比较这三个位置的元素,找到其中介于最小和最大之间的值。
  3. QuickSort函数:实现了快速排序的核心逻辑
    • 选择中间值,并将其与数组的第一个元素交换,作为基准值。
    • 遍历数组,将小于基准值的元素移到基准值左侧,大于基准值的元素移到右侧,相等的元素留在中间。
    • 对基准值左右两侧的子数组递归地进行快速排序,直到左右两侧都排好序

思路

这题有根据快排的痛点进行特地进行测试用例的编写

一开始大家肯定就直接放上去一个快排,结果发现:超时了(过不去的测试用例是有序的)

  • 所以第一次我们要加上三选一
  • 发现还不行(过不去的是数字全部一样),现在就考虑换上三路划分
  • 最后发现测试用例可以,但是时间过长,就改一下Getmid函数,之前mid ( l e f t + r i g h t ) / 2 (left+right)/2 (left+right)/2,现在是left+(rand()%(right-left))

好啦,排序的内容也到这里啦。下面就要开启c++的内容了

这篇关于数据结构排序——计数排序和排序总结(附上912. 排序数组讲解)的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/605176

相关文章

Python版本与package版本兼容性检查方法总结

《Python版本与package版本兼容性检查方法总结》:本文主要介绍Python版本与package版本兼容性检查方法的相关资料,文中提供四种检查方法,分别是pip查询、conda管理、PyP... 目录引言为什么会出现兼容性问题方法一:用 pip 官方命令查询可用版本方法二:conda 管理包环境方法

JavaScript对象转数组的三种方法实现

《JavaScript对象转数组的三种方法实现》本文介绍了在JavaScript中将对象转换为数组的三种实用方法,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友... 目录方法1:使用Object.keys()和Array.map()方法2:使用Object.entr

pycharm跑python项目易出错的问题总结

《pycharm跑python项目易出错的问题总结》:本文主要介绍pycharm跑python项目易出错问题的相关资料,当你在PyCharm中运行Python程序时遇到报错,可以按照以下步骤进行排... 1. 一定不要在pycharm终端里面创建环境安装别人的项目子模块等,有可能出现的问题就是你不报错都安装

Python内存管理机制之垃圾回收与引用计数操作全过程

《Python内存管理机制之垃圾回收与引用计数操作全过程》SQLAlchemy是Python中最流行的ORM(对象关系映射)框架之一,它提供了高效且灵活的数据库操作方式,本文将介绍如何使用SQLAlc... 目录安装核心概念连接数据库定义数据模型创建数据库表基本CRUD操作创建数据读取数据更新数据删除数据查

Java中实现对象的拷贝案例讲解

《Java中实现对象的拷贝案例讲解》Java对象拷贝分为浅拷贝(复制值及引用地址)和深拷贝(递归复制所有引用对象),常用方法包括Object.clone()、序列化及JSON转换,需处理循环引用问题,... 目录对象的拷贝简介浅拷贝和深拷贝浅拷贝深拷贝深拷贝和循环引用总结对象的拷贝简介对象的拷贝,把一个

Python中logging模块用法示例总结

《Python中logging模块用法示例总结》在Python中logging模块是一个强大的日志记录工具,它允许用户将程序运行期间产生的日志信息输出到控制台或者写入到文件中,:本文主要介绍Pyt... 目录前言一. 基本使用1. 五种日志等级2.  设置报告等级3. 自定义格式4. C语言风格的格式化方法

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

《JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法》:本文主要介绍JavaScript中比较两个数组是否有相同元素(交集)的三种常用方法,每种方法结合实例代码给大家介绍的非常... 目录引言:为什么"相等"判断如此重要?方法1:使用some()+includes()(适合小数组)方法2

Spring 依赖注入与循环依赖总结

《Spring依赖注入与循环依赖总结》这篇文章给大家介绍Spring依赖注入与循环依赖总结篇,本文通过实例代码给大家介绍的非常详细,对大家的学习或工作具有一定的参考借鉴价值,需要的朋友参考下吧... 目录1. Spring 三级缓存解决循环依赖1. 创建UserService原始对象2. 将原始对象包装成工

MySQL中查询和展示LONGBLOB类型数据的技巧总结

《MySQL中查询和展示LONGBLOB类型数据的技巧总结》在MySQL中LONGBLOB是一种二进制大对象(BLOB)数据类型,用于存储大量的二进制数据,:本文主要介绍MySQL中查询和展示LO... 目录前言1. 查询 LONGBLOB 数据的大小2. 查询并展示 LONGBLOB 数据2.1 转换为十

Unity新手入门学习殿堂级知识详细讲解(图文)

《Unity新手入门学习殿堂级知识详细讲解(图文)》Unity是一款跨平台游戏引擎,支持2D/3D及VR/AR开发,核心功能模块包括图形、音频、物理等,通过可视化编辑器与脚本扩展实现开发,项目结构含A... 目录入门概述什么是 UnityUnity引擎基础认知编辑器核心操作Unity 编辑器项目模式分类工程