排序算法——直接选择排序

news2024/11/13 21:34:25

直接选择排序

以升序排序为例

文章目录

  • 直接选择排序
    • 算法步骤
    • 动图演示
    • 实现代码
    • 改进算法(双指针)
      • 具体步骤
      • 处理特殊情况:
      • 实现代码
    • 时间复杂度

算法步骤

方法一:直接交换数组元素

  • 将第一个元素与其他元素进行比较,若其他元素小于第一个元素,则交换位置,最后第一个元素为最小元素
  • 将剩余元素的第一个元素与其他元素进行比较,若其他元素小于第一个元素,则交换位置
  • 重复上述步骤,直到第(n-1)个元素比较完毕

方法二:利用数组下标间接交换数组元素

  • 将第一个元素的下标标记为min,将第一个元素与其他元素进行比较,若其他元素小于第一个元素,则令该元素的数组下标为min,一轮比较完后,若第一个元素的下标不等于min,则交换第一个元素与下标为min的元素的位置
  • 对剩下的元素重复上述步骤,直到没有元素需要交换位置

动图演示

img

实现代码

#include<stdio.h>
void WayOne(int *p,int num)		//利用直接交换数组元素,从小到大排列数组
{
   int i,j,temp;
   for(i=0;i<num-1;i++)		//需比较(数组元素-1)次
   	for(j=i+1;j<num;j++)
   		if(p[i]>p[j])
   		{
   			temp=p[i];
   			p[i]=p[j];
   			p[j]=temp;
   		}
   for(i=0;i<num;i++)
   	printf("%-5d",p[i]);
}
void WayTwo(int *p,int num)		//利用元素下标间接交换数组元素,从大到小排列数组
{
   int i,j,temp,max;
   for(i=0;i<num-1;i++)
   {
   	max=i;			//设置标记
   	for(j=i+1;j<num;j++)
   		if(p[j]>p[max])
   			max=j;
   	if(max!=i)
   	{
   		temp=p[max];
   		p[max]=p[i];
   		p[i]=temp;
   	}
   }
   for(i=0;i<num;i++)
   	printf("%-5d",p[i]);
}
int main()
{
   int a[]={12,134,46,688,563,145,7357,26,24};
   WayOne(a,sizeof(a)/sizeof(int));
   printf("\n");
   WayTwo(a,sizeof(a)/sizeof(int));
   return 0;
}

改进算法(双指针)

具体步骤

  • 上面的直接选择排序每一次只能选出一个数据,但是,我们可以用双指针的方法进行改进,做到每一次可以选出两个数据

  • 首先,我们令begin指向数组第一个元素,end指向数组最后一个元素

  • 然后,遍历[begin,end]这一块区域,同时保存最大值和最小值元素的下标max_indexmin_index

  • 由于进行的是升序排序,begin位置应该放置最小值,end位置应该放置最大值,我们就可以利用下标来交换begin、min_index和end、max_index的数据

  • 缩小区域[begin,end],重复上述步骤,直到不能满足条件begin < end

  • 实现代码

    void SelectSort(int* nums, int numsSize)
    {
    	int begin = 0;
    	int end = numsSize - 1;
        
    	while (begin < end)
    	{
    		int max_index = end;
    		int min_index = begin;
    		for (int i = begin; i <= end; i++)
    		{
                //得到最小值的下标
    			if (nums[i] < nums[min_index])
    				min_index = i;
                
                //得到最大值的下标
    			if (nums[i] > nums[max_index])
    				max_index = i;
    		}
            
            //将最小值放到前面
    		Swap(&nums[begin], &nums[min_index]);
            
            //将最大值放到后面
    		Swap(&nums[end], &nums[max_index]);
            
            //缩小区间
    		begin++;
    		end--;
    	}
    }
    
  • 具体过程:

    在这里插入图片描述

处理特殊情况:

  • 如果遍历完后存在这么一种情况:

    在这里插入图片描述

  • 我们执行完第一次交换Swap(&nums[begin],&nums[min_index])后:

    在这里插入图片描述

  • 再执行第二次交换Swap(&nums[end], &nums[max_index]):

    在这里插入图片描述

  • 我们发现,最小值-1竟然被放到了最后,这显然是不对的,为什么会出现这样的情况呢?

  • 出现这种情况是因为:最大值元素的下标刚好是begin,当我们执行第一次交换Swap(&nums[begin], &nums[min_index])后,begin(max_index)代表的值就是最小值,因此当我们执行第二次交换Swap(&nums[end], &nums[max_index])时,就会将最小值放到最后(即end的位置)

  • 为了避免这种情况,应该在第一次交换后进行一次判断,对max_index的位置进行修正

    /*
    	如果 begin == max_index
    	那么第一次交换Swap(&nums[begin], &nums[min_index])后,min_index的值其实是最大值
    	因此,要将max_index的值修正为min_index
    */
    if (begin == max_index)
        max_index = min_index;
    

实现代码

void Swap(int* num1, int* num2)
{
	int temp = *num1;
	*num1 = *num2;
	*num2 = temp;
}

void SelectSort(int* nums, int numsSize)
{
	int begin = 0;
	int end = numsSize - 1;
    
	while (begin < end)
	{
		int max_index = end;
		int min_index = begin;
       for (int i = begin; i <= end; i++)
		{
            //得到最小值的下标
			if (nums[i] < nums[min_index])
				min_index = i;
            
            //得到最大值的下标
			if (nums[i] > nums[max_index])
				max_index = i;
		}
        
        //将最小值放到前面
		Swap(&nums[begin], &nums[min_index]);
        
        //对max_index进行修正
		if (begin == max_index)
			max_index = min_index;
        
        //将最大值放到后面
		Swap(&nums[end], &nums[max_index]);
        
        //缩小区间
		begin++;
		end--;
	}
}

时间复杂度

  • 直接选择排序虽然容易理解,但可以说是效率最低的一个排序算法
  • 在为改进的直接选择排序中,我们要遍历数组的每个元素,同时还要将每个元素和其他未有序的元素一一比较,因此时间复杂度为O(N2)
  • 在改进的直接选择排序中,最外层的while()循环的时间复杂度为O(N),里面for循环的时间复杂度也是O(N),因此整体的时间复杂度仍为O(N)
  • 综上,直接选择排序的时间复杂度为O(N2)

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

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

相关文章

初识网络之再看tcp协议

目录 一、tcp协议段格式 二、tcp协议的解包 三、tcp协议的分用 四、TCP可靠性问题 1. 不可靠存在原因 2. 常见的不可靠问题 3. 如何保证可靠性 4. 确认应答机制 5. 序号 五、tcp报头其余字段 1. 16位窗口大小 2. tcp的6个标记位 2.1 SYN 2.2 FIN 2.3 ACK 2.4 P…

【Linux】C语言中多线程的创建、退出、回收、分离

概述 线程是轻量级的进程&#xff08;LWP&#xff1a;light weight process&#xff09;&#xff0c;在 Linux 环境下线程的本质仍是进程。在计算机上运行的程序是一组指令及指令参数的组合&#xff0c;指令按照既定的逻辑控制计算机运行。操作系统会以进程为单位&#xff0c;…

【Spring AOP】面向切面编程

&#x1f389;&#x1f389;&#x1f389;点进来你就是我的人了博主主页&#xff1a;&#x1f648;&#x1f648;&#x1f648;戳一戳,欢迎大佬指点! 欢迎志同道合的朋友一起加油喔&#x1f93a;&#x1f93a;&#x1f93a; 目录 1. 什么是Spring AOP&#xff1f; 2. 为什么要…

NFC type 12345 tag介绍

NFC(近场通信)被称为短距离无线技术&#xff0c;是一套通信协议&#xff0c;NFC技术将非接读卡器/Reader、非接标签/Tag和点对点(Peer-to-Peer)数据交换的功能设计融为一体!使电子设备之间能够进行简单、安全的双向交互。为推动NFC技术发展&#xff0c;2004年&#xff0c;诺基亚…

Stable-Diffusion环境搭建

硬件可以采用DELL R7525 搭配L4 或者T4 等等企业级显卡 环境如下&#xff1a; 可以看到有相应的GPU卡信息 esxi 7.u3 信息 设置GPU穿透方式 查看相应的虚拟机参数信息 PCI 设备加载穿透GPU信息 启动uefi 设置相应的参数信息 https://docs.nvidia.com/grid/latest/grid-vgpu-re…

如何检测视频中的绿屏、绿帧问题

今天给项目拷机&#xff0c;发现视频会偶现绿屏&#xff0c;非常偶现&#xff0c;很难复现出来。 由于问题暂时没有定位&#xff0c;只能先表面解决一下&#xff0c;就是过滤掉出现绿屏的帧。 当然&#xff0c;首先要把绿帧检测出来&#xff0c;才能做后续的补救措施。 绿屏、…

电感公式推导

目录 电感的磁感应强度用&#xff1a;B表示 加入磁芯的可以提高磁感应强度&#xff1a;BμNI &#xff08;μ > μ0&#xff09; 磁芯的磁通量用&#xff1a;Φ来表示 一匝线圈感生电动势用&#xff1a;E来表示 在整个电感线圈的里面产生的感生电动势用UL来表示&#xff…

软件测试项目实战,电商项目核心业务测试分析(全覆盖)

目录&#xff1a;导读 前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09; 前言 登陆功能怎么测试…

第16章_多版本并发控制

第16章_多版本并发控制 1. 什么是MVCC MVCC(Multiversion Concurrency Control)&#xff0c;多版本并发控制。顾名思义&#xff0c;MVCC是通过数据行的多个版本管理来实现数据库的并发控制。这项技术使得在InnoDB的事务隔离级别下执行一致性读操作有了保证。换言之&#xff0…

chapter9: SpringBoot自定义Starter

尚硅谷SpringBoot顶尖教程 1. 自定义starter介绍 自定义starter从下面两个方面着手&#xff1a; 这个自定义starter的场景需要用到哪些依赖&#xff1f;如何编写自定义starter的自动配置&#xff1f; 查看springboot提供的已有starter组件的自动配置类&#xff0c;基本使用…

NFC Forum Type2 Tag

RC522作为一款NFC读写芯片&#xff0c;性价比还是很高的&#xff0c;因为在项目里需要采用NFC OOB配对&#xff0c;所以需要读取配对方模拟的NFC卡片信息 读取对象采用NRF52832&#xff0c;使用其NFC功能模拟type2 tag&#xff0c;但是读取方式和M1卡不一样&#xff0c;踩了不…

软件测试员不要过于迷信技术,忽视软技能

精于技术对于测试员&#xff0c;乃至技术员本身没毛病&#xff0c;甚至应大加赞赏&#xff0c;在组织中更应像国宝熊猫一样照顾好。然而我们发现&#xff0c;一些精于技术的测试员混的并不好。“纯正”的技术人员就该吃亏&#xff1f;问题到底出现在哪里&#xff1f; 根据我对…

南大通用GBase 8c 多模多态分布式数据库系列二之安装与卸载

目录 一.前言 二. 学习目标 三. 安装流程 四. 配置要求 1. 硬件配置要求 2. 软件配置要求 3. 软件依赖配置 五. 集群规划 1. 物理规划 2. 演示环境配置 六. 安装前环境检查 1. 关闭防火墙 2. 关闭SELINUX 3. 主机名检查、依赖检查 4. Gbase用户配置sudo 七. 配…

科研闭环指南|关于 Review Rebuttal 的二三事

两个月前投稿的论文审稿&#xff08;Review&#xff09;意见快下来了&#xff0c;期间我也是作为审稿人&#xff08;Reviewer&#xff09;完成了4篇工作的审稿工作。回想自己从入学以来也算是审过 10 篇左右的稿子了&#xff0c;也参与过 Review 之后的 Rebuttal 环节。下面我就…

思维决定发展,软件测试人也不例外

最近特别懒&#xff0c;不想码字&#xff0c;原本写作就很差&#xff0c;更是退化严重。社招和校招面试过很多人&#xff0c;从十年前自己还很弱的时候学着面试&#xff0c;到数百次面试积累之后&#xff0c;面对候选人的时候&#xff0c;我的内心依然有些许紧张&#xff0c;非…

《Reinforcement Learning: An Introduction》第5章笔记

Chapter 5 Monte Carlo Methods Monte Carlo 方法不假设拥有完备的环境知识&#xff0c;它仅仅需要经验–从与环境的实际或模拟交互中得到的一系列的状态、动作、和奖励的样本序列。 Monte Carlo方法是基于平均采样回报的来解决强化学习问题的方法。 5.1 Monte Carlo Predic…

NFS服务器

文章目录 NFS服务器NFS的由来与功能什么是NFS(Network File System)什么是RPC(Remote Procedure Call)NFS启动的RPC daemons NFS Server 端的配置所需要的软件NFS的软件结构/etc/exports配置文件的语法与参数 启动NFSRPC服务的注册状况怎么查看(rpcinfo) NFS的连接查看showmoun…

认识服务器

1、查看操作系统的信息 CentOS 输入&#xff1a;cat /etc/os-release 字段含义解释NAME操作系统名称CentOS LinuxVERSION操作系统版本7 (Core)ID操作系统标识centosID_LIKE相关操作系统标识rhel fedoraVERSION_ID操作系统版本号7PRETTY_NAME可读性较好的操作系统名称CentOS L…

产品如何有效把控产品上线质量

很多人乍看这个标题&#xff0c;可能有些惊讶。产品上线质量不是由测试来主要负责的么&#xff0c;怎么产品也需要来把控这个事情&#xff1f; 诚然&#xff0c;从具体分工而言&#xff0c;产品的线上质量主要由测试来负责&#xff0c;产品按时按量完成由项目项目经理把控。但…

详谈数据中心网络中的四种虚拟化技术:VXLAN、NVGRE、STT和SPBM

概要 在现代的数据中心网络中&#xff0c;虚拟化技术被广泛应用以提供更高的可扩展性、灵活性和效率。数据中心网络虚拟化允许多个虚拟网络在共享的物理基础设施上运行&#xff0c;使得网络资源的管理更为简单和高效。本文将详细介绍数据中心网络中的四种不同类型的虚拟化技术&…