排序(2)

news2024/9/21 16:18:31

我们在排序(1)中说到选择排序的代码:

void SelectSort(int* a,int n)
{
   int begin=0,end=n-1;
   int mini=begin,max=begin;
   for(int i=begin+1;i<=end;i++)
   {
      if(a[i]>a[max])
      {
         maxi=i;
      }
      if(a[i]<a[mini])
      {
         mini=i;
      }
    ++begin;
    --end;
   }
   Swap(&a[beign],&a[mini]);
   Swap(&a[end],&a[maxi]);
}

那么当我们解决下面这个问题的时候:当开始时,begin=0,end=7,mini=begin=0,maxi=begin=0。i=1,1小于0,所以mini=1。a[mini]=1,++begin,begin=1,--end,end=6。此时最大值是9(begin),最小值是1(i)。

i=2,begin=1,end=6。

当begin和max重合,就会出现

4 3 5 6 

正确的代码应该是这样的:

void SelectSort(int* a,int n)
{
   int begin=0,end=n-1;
   int mini=begin,maxi=begin;
   for(int i=begin+1;i<=end;i++)
   {
      if(a[i]>a[max])
      {
         maxi=i;
      }
      if(a[i]<a[mini])
      {
         mini=i;
      }
   }
   Swap(&a[begin],&a[mini]);
   if(maxi==begin)
   {
      maxi=mini;
    }
   Swap(&a[end],&a[maxi]);
   ++begin;
    --end;
}

快速排序

把小的换到左边,把大的换到右边。

动图链接地址如下:

https://gitee.com/bithange/113-issues/raw/master/24%E5%B9%B4-05%E6%9C%8827%E6%97%A5--%E6%8E%92%E5%BA%8F/%E5%8A%A8%E5%9B%BE/hoare.gif 单趟快排代码如下:

void QuickSort(int* a,int left,int right)
{
   int key=a[left];
   int begin=left,end=right;
   while(begin<end)
   {
     //右边找小
     while(begin<end&&a[end]>=key)//加等号,相等的值放左边或者右边都无所谓
     {
        --end;
     }
     //左边找大
     while(begin<end&&a[begin]>key)
     {
        ++begin;
      }
     Swap(&a[begin],&a[end]);
    }
    Swap(key,&a[begin]);
}
   
   

这段代码有一些问题,让我们逐个解决吧!

首先,记录值只是复制了一个值,比如
int a = 10;
int b = a;
修改b的值对a的值没有影响
记录索引,修改的就是索引对应的值

什么情况下不需要对数组进行分割了呢?一种是这个区间只有一个值,另一只种是这个区间不存在。(结束条件)
 

void QuickSort(int* a,int left,int right)
{
   int keyi=left;
   int begin=left,end=right;
   if(left>right)
     return;
   while(begin<end)
   {
     //右边找小
     while(begin<end&&a[end]>=key)//加等号,相等的值放左边或者右边都无所谓
     {
        --end;
     }
     //左边找大
     while(begin<end&&a[begin]>key)
     {
        ++begin;
      }
     Swap(&a[begin],&a[end]);
    }
    Swap(&a[keyi],&a[begin]);
    keyi=begin;
    //[left,keyi-1] keyi [keyi+1,right]'
    QuickSort(a,left,keyi-1);
    QuickSort(a,keyi+1,right);
}
   
   

选key如果每一次都在最前面,那么就不合理,我们期望选择的key每次都是最中间的值。

1随机数选key

2三数取中(把选中的数挪到最左边)

int GetMid(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 right;
       }
      else
         return left;
   }
   else
   {
      if(a[mid]>a[right])
      {
         return mid;
      }
      else if(a[left]<a[right])
      {
         return left;
      }
      else
         return right;
   }
}
   

但是当需要排序的数字只有几个时,需要进行的趟数就多了,而且很浪费。所以,在进行判断时,我们需要加上一个条件。那么在这样一个数字较少的情况下,我们应该选择哪种排序呢?希尔排序的优势就是让大的数更快跳到后面,小的数更快跳到前面。

int GetMid(int* a,int left,int right)
{
   if(right-left+1<10)//小区间优化,不再递归分割排序,减少递归次数
   {
      InsertSort(a+left,right-left+1);
   }
   else
   {
   int mid=(left+right)/2;
   if(a[left]<a[mid])
   {
      if(a[mid]<a[right])
      {
         return mid;
      }
      else if(a[left]<a[right])
      {
        return right;
       }
      else
         return left;
   }
   else
   {
      if(a[mid]>a[right])
      {
         return mid;
      }
      else if(a[left]<a[right])
      {
         return left;
      }
      else
         return right;
   }
   }
}
   

结论:左边做key,右边先走,可以保证相遇位置的值比key要小。
相遇的场景分析:
L遇R:R先走,停下来,R停下条件是遇到比key小的值,R停的位置一定比key小,L没有找大的,遇到R停下了
R遇L:R先走,找小,没有找到比key小的,直接跟L相遇了。L停留的位置是上一轮交换的位置,上一轮交换,把比key小的值,换到L的位置了

相反,让右边做key,左边先走,可以保证相遇位置的值比key要大。

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

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

相关文章

UE5 05-利用 timeline 插值运动

理解成 unity Dotween DoMove 插值运动即可 AddTimeLine 节点 物体插值运动 物体插值缩放 一个timeline 可以K多个动画帧

C语言 printf 函数多种输出格式以及占位输出

一、输出格式 在C语言中&#xff0c;printf 函数提供了多种输出格式&#xff0c;用于控制不同类型数据的输出方式。 1.整数输出格式 %d&#xff1a;以十进制形式输出整数。 %o&#xff1a;以八进制形式输出整数&#xff08;无前导0&#xff09;。 %x 或 %X&#xff1a;以十六进…

包/final/权限修饰符/代码块

包package 1、包的作用 包用来管理不同的类。 2、包名 包名要全部小写&#xff0c;一般是域名反写&#xff0c;如com.liu。在Java中&#xff0c;java解释器会将package中的.解释为目录分隔符/&#xff0c;也就是说该文件的目录结构为&#xff1a;...com/liu/... 3、全类名…

Nginx 报错问题汇总

目录 一、nginx: [emerg] invalid number of arguments in "include" directive in C:\Program Files\nginx-1.15.4/conf/nginx.conf:61 总结&#xff1a; 二、nginx: [error] OpenEvent("Global\ngx_reload_2152") failed (5: Access is denied) 解决…

《昇思25天学习打卡营第14天|onereal》

第14天学习内容如下&#xff1a; Diffusion扩散模型 本文基于Hugging Face&#xff1a;The Annotated Diffusion Model一文翻译迁移而来&#xff0c;同时参考了由浅入深了解Diffusion Model一文。 本教程在Jupyter Notebook上成功运行。如您下载本文档为Python文件&#xff0c…

LabVIEW的JKI State Machine

JKI State Machine是一种广泛使用的LabVIEW架构&#xff0c;由JKI公司开发。这种状态机架构在LabVIEW中提供了灵活、可扩展和高效的编程模式&#xff0c;适用于各种复杂的应用场景。JKI State Machine通过状态的定义和切换&#xff0c;实现了程序逻辑的清晰组织和管理&#xff…

IDEA常用技巧荟萃:精通开发利器的艺术

1 概述 在现代软件开发的快节奏环境中,掌握一款高效且功能全面的集成开发环境(IDE)是提升个人和团队生产力的关键。IntelliJ IDEA,作为Java开发者的首选工具之一,不仅提供了丰富的编码辅助功能,还拥有高度可定制的界面和强大的插件生态系统。然而,要充分发挥其潜力,深…

[激光原理与应用-101]:南京科耐激光-激光焊接-焊中检测-智能制程监测系统IPM介绍 - 5 - 3C行业应用 - 电子布局类型

目录 前言&#xff1a; 一、激光在3C行业的应用概述 1.1 概述 1.2 激光焊接在3C-电子行业应用 二、3C电子行业中激光焊接 2.1 纽扣电池 2.2 均温板 2.3 指纹识别器 2.4 摄像头模组 2.5 IC芯片切割 三、3C行业中激光切割 四、激光在3C行业中的其他应用 4.1 涂层去除…

SpringBoot源码阅读(1)——环境搭建

SpringBoot官网 官网 https://spring.io/projects/spring-boot 代码仓库 github&#xff1a;https://github.com/spring-projects/spring-boot gitee: https://gitee.com/mirrors/spring-boot 下载代码 git clone https://gitee.com/mirrors/spring-boot.git下载的代码中有些…

STM32-OC输出比较和PWM

本内容基于江协科技STM32视频内容&#xff0c;整理而得。 文章目录 1. OC输出比较和PWM1.1 OC输出比较1.2 PWM&#xff08;脉冲宽度调制&#xff09;1.3 输出比较通道&#xff08;高级&#xff09;1.4 输出比较通道&#xff08;通用&#xff09;1.5 输出比较模式1.6 PWM基本结…

数据库逆向工程工具reverse_sql

reverse_sql 是一个用于解析和转换 MySQL 二进制日志&#xff08;binlog&#xff09;的工具。它可以将二进制日志文件中记录的数据库更改操作&#xff08;如插入、更新、删除&#xff09;转换为反向的 SQL 语句&#xff0c;以便对系统或人为产生的误操作进行数据回滚和恢复。 *…

LabVIEW的Actor Framework (AF) 结构介绍

LabVIEW的Actor Framework (AF) 是一种高级架构&#xff0c;用于开发并发、可扩展和模块化的应用程序。通过面向对象编程&#xff08;OOP&#xff09;和消息传递机制&#xff0c;AF结构实现了高效的任务管理和数据处理。其主要特点包括并发执行、动态可扩展性和强大的错误处理能…

图神经网络实战(16)——经典图生成算法

图神经网络实战&#xff08;16&#xff09;——经典图生成算法 0. 前言1. 图生成技术2. Erdős–Rnyi模型3. 小世界模型小结系列链接 0. 前言 图生成算法是指用于创建模拟图或网络结构的算法&#xff0c;这些算法可以根据特定的规则和概率分布生成具有特定属性的图&#xff0c…

华为OSPF配置DR和BDR与指定DR

基础配置 <Huawei>sys #进入配置模式 Enter system view, return user view with CtrlZ. [Huawei]un in en #关闭报文弹窗 Info: Information center is disabled. [Huawei]sys R1 #设备名更改为R1 [R1]int g0/0/0 …

Vue3中的Composables组合式函数,Vue3实现minxins

Vue3中的Composables是什么 Vue3中的Composables 简单理解其实就是类React Hooks式的组合式函数封装方法。 Vue官方称为Composables 组合式函数。 1.抽离复用逻辑时 Vue2写法 &#xff08;1&#xff09;Vue2 中的mixins混入器写法缺点 (Vue3 optionsApi写法同理) 新建minxins…

硅纪元视角 | 中国电信“星辰大模型·软件工厂”,两分钟完成应用开发,效率飞跃!

在数字化浪潮的推动下&#xff0c;人工智能&#xff08;AI&#xff09;正成为塑造未来的关键力量。硅纪元视角栏目紧跟AI科技的最新发展&#xff0c;捕捉行业动态&#xff1b;提供深入的新闻解读&#xff0c;助您洞悉技术背后的逻辑&#xff1b;汇聚行业专家的见解&#xff0c;…

动手学深度学习(Pytorch版)代码实践 -循环神经网络- 56门控循环单元(`GRU`)

56门控循环单元&#xff08;GRU&#xff09; 我们讨论了如何在循环神经网络中计算梯度&#xff0c; 以及矩阵连续乘积可以导致梯度消失或梯度爆炸的问题。 下面我们简单思考一下这种梯度异常在实践中的意义&#xff1a; 我们可能会遇到这样的情况&#xff1a;早期观测值对预测…

Windows电脑下载、安装VS Code的方法

本文介绍Visual Studio Code&#xff08;VS Code&#xff09;软件在Windows操作系统电脑中的下载、安装、运行方法。 Visual Studio Code&#xff08;简称VS Code&#xff09;是一款由微软开发的免费、开源的源代码编辑器&#xff0c;支持跨平台使用&#xff0c;可在Windows、m…

C++ 模版进阶

目录 前言 1. 非类型模版参数 1.1 概念与讲解 1.2 array容器 2. 模版的特化 2.1 概念 2.2 函数模版特化 2.3 类模版特化 2.3.1 全特化 2.3.2 偏特化 3.模版的编译分离 3.1 什么是分离编译 3.2 模版的分离编译 3.3 解决方法 4. 模版总结 总结 前言 本篇文章主要…

在mac下 Vue2和Vue3并存 全局Vue2环境创建Vue3新项目(Vue cli2和Vue cli4)

全局安装vue2 npm install vue-cli -g自行在任意位置创建一个文件夹vue3&#xff0c;局部安装vue3,注意不要带-g npm install vue/cli安装完成后&#xff0c;进入目录&#xff0c;修改vue为vue3 找到vue3/node-moudles/.bin/vue&#xff0c;把vue改成vue3。 对环境变量进行配置…