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

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

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

现在常见算法排序都已讲解完成,今天就再讲个计数排序。再总结一下


1.计数排序


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


步骤:


找出待排序的数组中最大和最小的元素:min和max

统计数组中每个值为 i 的元素出现的次数,存入新建数组 C 的第 i-min 项(c初始化时都是0),每遇到一次,对应下标上的数就++

反向填充目标数组:利用新建的数组把数据覆盖回去


时间复杂度: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;
}


Swap函数: 这是一个用于交换两个整数值的简单函数。

GetMid函数: 用于在数组中找到三个位置(左、中、右)的元素,从而选取合适的中间值。它通过比较这三个位置的元素,找到其中介于最小和最大之间的值。

QuickSort函数:实现了快速排序的核心逻辑

选择中间值,并将其与数组的第一个元素交换,作为基准值。

遍历数组,将小于基准值的元素移到基准值左侧,大于基准值的元素移到右侧,相等的元素留在中间。

对基准值左右两侧的子数组递归地进行快速排序,直到左右两侧都排好序


思路


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


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


所以第一次我们要加上三选一

发现还不行(过不去的是数字全部一样),现在就考虑换上三路划分

最后发现测试用例可以,但是时间过长,就改一下Getmid函数,之前mid是( l e f t + r i g h t ) / 2 (left+right)/2(left+right)/2,现在是left+(rand()%(right-left))


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


目录
相关文章
|
8月前
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
293 29
|
8月前
|
存储 人工智能 算法
C 408—《数据结构》算法题基础篇—数组(通俗易懂)
408考研——《数据结构》算法题基础篇之数组。(408算法题的入门)
291 23
|
9月前
|
存储 人工智能 算法
【C++数据结构——内排序】二路归并排序(头歌实践教学平台习题)【合集】
本关任务是实现二路归并算法,即将两个有序数组合并为一个有序数组。主要内容包括: - **任务描述**:实现二路归并算法。 - **相关知识**: - 二路归并算法的基本概念。 - 算法步骤:通过比较两个有序数组的元素,依次将较小的元素放入新数组中。 - 代码示例(以 C++ 为例)。 - 时间复杂度为 O(m+n),空间复杂度为 O(m+n)。 - **测试说明**:平台会对你编写的代码进行测试,提供输入和输出示例。 - **通关代码**:提供了完整的 C++ 实现代码。 - **测试结果**:展示代码运行后的排序结果。 开始你的任务吧,祝你成功!
207 10
|
9月前
|
搜索推荐 算法 数据处理
【C++数据结构——内排序】希尔排序(头歌实践教学平台习题)【合集】
本文介绍了希尔排序算法的实现及相关知识。主要内容包括: - **任务描述**:实现希尔排序算法。 - **相关知识**: - 排序算法基础概念,如稳定性。 - 插入排序的基本思想和步骤。 - 间隔序列(增量序列)的概念及其在希尔排序中的应用。 - 算法的时间复杂度和空间复杂度分析。 - 代码实现技巧,如循环嵌套和索引计算。 - **测试说明**:提供了测试输入和输出示例,帮助验证代码正确性。 - **我的通关代码**:给出了完整的C++代码实现。 - **测试结果**:展示了代码运行的测试结果。 通过这些内容,读者可以全面了解希尔排序的原理和实现方法。
151 10
|
9月前
|
搜索推荐 C++
【C++数据结构——内排序】快速排序(头歌实践教学平台习题)【合集】
快速排序是一种高效的排序算法,基于分治策略。它的主要思想是通过选择一个基准元素(pivot),将数组划分成两部分。一部分的元素都小于等于基准元素,另一部分的元素都大于等于基准元素。然后对这两部分分别进行排序,最终使整个数组有序。(第一行是元素个数,第二行是待排序的原始关键字数据。本关任务:实现快速排序算法。开始你的任务吧,祝你成功!
203 7
|
11月前
|
存储 缓存 算法
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式
在C语言中,数据结构是构建高效程序的基石。本文探讨了数组、链表、栈、队列、树和图等常见数据结构的特点、应用及实现方式,强调了合理选择数据结构的重要性,并通过案例分析展示了其在实际项目中的应用,旨在帮助读者提升编程能力。
288 5
|
11月前
|
存储 人工智能 算法
数据结构实验之C 语言的函数数组指针结构体知识
本实验旨在复习C语言中的函数、数组、指针、结构体与共用体等核心概念,并通过具体编程任务加深理解。任务包括输出100以内所有素数、逆序排列一维数组、查找二维数组中的鞍点、利用指针输出二维数组元素,以及使用结构体和共用体处理教师与学生信息。每个任务不仅强化了基本语法的应用,还涉及到了算法逻辑的设计与优化。实验结果显示,学生能够有效掌握并运用这些知识完成指定任务。
201 4
|
12月前
|
算法 程序员 索引
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
栈的基本概念、应用场景以及如何使用数组和单链表模拟栈,并展示了如何利用栈和中缀表达式实现一个综合计算器。
179 1
数据结构与算法学习七:栈、数组模拟栈、单链表模拟栈、栈应用实例 实现 综合计算器
|
12月前
|
算法 搜索推荐 Java
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
基数排序是一种稳定的排序算法,通过将数字按位数切割并分配到不同的桶中,以空间换时间的方式实现快速排序,但占用内存较大,不适合含有负数的数组。
178 0
数据结构与算法学习十三:基数排序,以空间换时间的稳定式排序,速度很快。
|
12月前
|
存储 算法 定位技术
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列
这篇文章主要介绍了稀疏数组和队列的概念、应用实例以及如何使用数组模拟队列和环形队列的实现方法。
130 0
数据结构与算法学习二、稀疏数组与队列,数组模拟队列,模拟环形队列