【数据结构】-8种排序解析(详细总结,简洁,含代码,例题)(一)

简介: 【数据结构】-8种排序解析(详细总结,简洁,含代码,例题)

一.8种排序方式总览分析(带图)

   1.按方式分类(比较排序)

image.png

*计数排序:非比较排序

二.8种排序方式详细解析

    1.计数排序

注意:计数排序适合范围集中,且范围不大的整型数组排序。不适合范围分散或者非整型的排序,如:字符串、浮点数 等


步骤:


1.找到原数组最大的值,记作range


2.设置一个计数数组,遍历一遍原数组O(n),统计每个数据出现的次数。


3.遍历一遍计数数组O(range)


计数排序分为:相对映射型和非相对映射型(相对位置)


图示意:

image.png

 2.冒泡排序

遍历有序区间的各个数,从其开始到结尾的区间内轮转交换不断缩小区间

原理:不断把大/小的数移到后面

注意点:为提高效率,当发现一次循环中没有数对交换,即可中止循环。

void BubbleSort(int*a,int n)
{
  int i = 0,j=0;
  for (j = 0; j<n; j++)
  {
    bool exchange = false;
    for (i = 0; i < n-j; i++)
    {
      if (a[i + 1] < a[i])
      {
        Swap(&a[i + 1], &a[i]);
        exchange = true;
      }
    }
        //加入判断环节,提前终止,提高效率
    if (exchange == false)
    {
      break;
    }
  }
}

    3.选择排序

遍历有序区间的各个数,找出其之后的最大/最小数并与该数之后的数进行替换。


代码的设计思路是设置left,right下标从数组两端向中间遍历,依次筛选出最大值和最小值mini,maxi,并分别与left,riight进行交换。


注意点:在交换过程中,left所处的位置可能正好被maxi标记,接下来下一步maxi与right的交换则会出错,right无法与正确的maxi交换。


解决方法:如果left和maxi重叠,交换后要修正

void SelectSort(int* a, int n)
{
  int left = 0;
  int right = n;
  while (left < right)
  {
    int mini = left, maxi = right;
    for (int i =left+1; i <= right; i++)
    {
      if (a[i] > a[maxi])
      {
        maxi = i;//移动下标
      }
      if (a[i] < a[mini])
      {
        mini = i;
      }
    }
    Swap(&a[left], &a[mini]);
    if (left == maxi)
    {
      maxi = mini;
    }
    Swap(&a[right], &a[maxi]);
    left++;
    right--;
  }
}

 4.插入排序

遍历有序区间的各个数,把其视作临时变量tmp,分别于它前面的数进行对比,

其进一步优化即为“希尔排序”

注意点:此算法中,当tmp比第一个数大/小时,end会到-1的位置。所以采用图中标记用法

image.png

//升序
void InsertSort(int* a, int n)//a 数组  n 个数
{
  int i = 0;
  for (i = 1; i < n; i++)
  {
    int end = i - 1;
    int tmp = i;
    while (end >= 0)
    {
      if (a[tmp] < a[end])
      {
        //整体后移
        a[end + 1] = a[end];
        --end;
      }
      else
      {
        break;
      }
    }
    //填空
    a[end + 1] = a[tmp];
  }
}

5.希尔排序

其可以理解为在插入排序的基础上进行预排序(分组插排)

注意点:图示辅助理解循环:

image.png

void ShellSort(int* a, int n)
{
  //gap==1 插入排序
  //gap>1预先排序
  int gap=n;
  //升序
  while(gap>1)
  { 
    gap = gap / 2;
    //gap=gap/3+1     确保gap的跳跃到最后为1,
    int i = 0;
    for (i = 0; i < n-gap; i++)
    {
      int end = i;
      int tmp = i+gap;
      while (end >= 0)
      {
        if (a[tmp] < a[end])
        {
          //整体后移
          a[end + gap] = a[end];
          end -= gap;
        }
        else
        {
          break;
        }
      }
      //填空
      a[end + gap] = a[tmp];
    }
  }
}

 6.堆排序

详情可见博主关于堆排详解:

image.png

 7.快速排序(递归和非递归写法)

任取待排序元素序列中的某元素作为基准值,按照该排序码将待排序集合分割成两子序列,左子序列中的所有元素均小于基准值,右子序列中所有元素均大于基准值,然后最左右子序列重复该过程,直到所有元素都排列在相应位置上为止。


注意点:当快速排序接近二分(二叉树)的递归模式时,效率最高。因此引入“三数取中”优化代码:

int GetMidNumi(int* a, int left, int right)
{
  int mid = (left + right) / 2;
  if (a[left] < a[mid])
  {
    if (a[mid] < a[right])
    {
      return mid;
    }
    else if (a[left] > a[right])
    {
      return left;
    }
    else
    {
      return right;
    }
  }
  else // a[left] > a[mid]
  {
    if (a[mid] > a[right])
    {
      return mid;
    }
    else if (a[left] < a[right])
    {
      return left;
    }
    else
    {
      return right;
    }
  }
}

    1.三种排序方式

 1.交换法


  1.左边做key,右边先走——保证相遇位置比key小


    ps:【右边先走找比key小的数,则其停止位置一定小于等于key】


  2.由于左右相遇的位置一定比key小,把左边与相遇位置替换


图示:

image.png


image.png

代码:

2.挖坑法

  1.先将左边第一个数据放在临时变量key中,原地形成一个坑位

 2.右边先动,找小于key的数,放到坑位中,并且原地新生成一个坑位

 3.当左右相遇时,将key填入最后一个坑位中

1.png

3.前后指针法(玩区间)


 1.左边第一个数设为key,prev(延迟指针),cur(实时指针)


 2.cur开始向右移动,找到比key小的值prev和cur同时移动


 3.找到比key大的值只移动cur——保证prev和cur中间隔着一段比key大的区间


 4.找到比key小的值时,交换prev下一个位置(比key大的区间)和cur位置的值——比key大的值翻到区间右边,把比key小的值翻到区间左边。

图示:

2.png

相关文章
|
前端开发 Java
java实现队列数据结构代码详解
本文详细解析了Java中队列数据结构的实现,包括队列的基本概念、应用场景及代码实现。队列是一种遵循“先进先出”原则的线性结构,支持在队尾插入和队头删除操作。文章介绍了顺序队列与链式队列,并重点分析了循环队列的实现方式以解决溢出问题。通过具体代码示例(如`enqueue`入队和`dequeue`出队),展示了队列的操作逻辑,帮助读者深入理解其工作机制。
579 1
|
算法 PyTorch 算法框架/工具
昇腾 msmodelslim w8a8量化代码解析
msmodelslim w8a8量化算法原理和代码解析
1153 5
|
搜索推荐 UED Python
实现一个带有昼夜背景切换的动态时钟:从代码到功能解析
本文介绍了一个使用Python和Tkinter库实现的动态时钟程序,具有昼夜背景切换、指针颜色随机变化及整点和半点报时功能。通过设置不同的背景颜色和随机变换指针颜色,增强视觉吸引力;利用多线程技术确保音频播放不影响主程序运行。该程序结合了Tkinter、Pygame、Pytz等库,提供了一个美观且实用的时间显示工具。欢迎点赞、关注、转发、收藏!
604 94
|
人工智能 文字识别 自然语言处理
保单AI识别技术及代码示例解析
车险保单包含基础信息、车辆信息、人员信息、保险条款及特别约定等关键内容。AI识别技术通过OCR、文档结构化解析和数据校验,实现对保单信息的精准提取。然而,版式多样性、信息复杂性、图像质量和法律术语解析是主要挑战。Python代码示例展示了如何使用PaddleOCR进行保单信息抽取,并提出了定制化训练、版式分析等优化方向。典型应用场景包括智能录入、快速核保、理赔自动化等。未来将向多模态融合、自适应学习和跨区域兼容性发展。
938 29
|
存储 机器学习/深度学习 算法
C 408—《数据结构》图、查找、排序专题考点(含解析)
408考研——《数据结构》图,查找和排序专题考点选择题汇总(含解析)。
1243 29
|
存储 机器学习/深度学习 人工智能
C 408—《数据结构》易错考点200题(含解析)
408考研——《数据结构》精选易错考点200题(含解析)。
1652 27
|
传感器 监控 Java
Java代码结构解析:类、方法、主函数(1分钟解剖室)
### Java代码结构简介 掌握Java代码结构如同拥有程序世界的建筑蓝图,类、方法和主函数构成“黄金三角”。类是独立的容器,承载成员变量和方法;方法实现特定功能,参数控制输入环境;主函数是程序入口。常见错误包括类名与文件名不匹配、忘记static修饰符和花括号未闭合。通过实战案例学习电商系统、游戏角色控制和物联网设备监控,理解类的作用、方法类型和主函数任务,避免典型错误,逐步提升编程能力。 **脑图速记法**:类如太空站,方法即舱段;main是发射台,static不能换;文件名对仗,括号要成双;参数是坐标,void不返航。
545 5
|
自然语言处理 搜索推荐 数据安全/隐私保护
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
鸿蒙登录页面设计展示了 HarmonyOS 5.0(Next)的未来美学理念,结合科技与艺术,为用户带来视觉盛宴。该页面使用 ArkTS 开发,支持个性化定制和无缝智能设备连接。代码解析涵盖了声明式 UI、状态管理、事件处理及路由导航等关键概念,帮助开发者快速上手 HarmonyOS 应用开发。通过这段代码,开发者可以了解如何构建交互式界面并实现跨设备协同工作,推动智能生态的发展。
886 10
鸿蒙登录页面好看的样式设计-HarmonyOS应用开发实战与ArkTS代码解析【HarmonyOS 5.0(Next)】
|
SQL Java 数据库连接
如何在 Java 代码中使用 JSqlParser 解析复杂的 SQL 语句?
大家好,我是 V 哥。JSqlParser 是一个用于解析 SQL 语句的 Java 库,可将 SQL 解析为 Java 对象树,支持多种 SQL 类型(如 `SELECT`、`INSERT` 等)。它适用于 SQL 分析、修改、生成和验证等场景。通过 Maven 或 Gradle 安装后,可以方便地在 Java 代码中使用。
4670 11
|
PHP 开发者 容器
PHP命名空间深度解析:避免命名冲突与提升代码组织####
本文深入探讨了PHP中命名空间的概念、用途及最佳实践,揭示其在解决全局命名冲突、提高代码可维护性方面的重要性。通过生动实例和详尽分析,本文将帮助开发者有效利用命名空间来优化大型项目结构,确保代码的清晰与高效。 ####
239 20

推荐镜像

更多
  • DNS