拒绝水文!八大排序(一)【适合初学者】直接插入排序和希尔排序

news2024/11/27 11:41:56

文章目录

  • 直接插入排序
  • 希尔排序

大家好,我是纪宁。
这篇文章将向大家介绍直接插入排序算法和希尔排序算法。

直接插入排序

直接插入排序是一个简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
像你玩扑克牌一样,每接到一张排,会习惯性的将它插入到合适的位置当中,最后你会得到一副整齐的牌,插入排序就是这样的原理。
在这里插入图片描述

插入排序动态图解

在这里插入图片描述
假如现在要进升序排序,那么就需要从第二个数据开始依次 ‘插入’ 到原序列。

具体步骤(以升序为例子)
从第二个数据开始,先保存这个数据 A,然后将数据 A 依次与它前面的数据进行比较,如果数据A 小于前面的数(说明A的位置应该在这个数前面),那么前面的数就后移一个位置,直到数据A 大于等于前面的某个数,就将数据A 放在这个数的后面(这个数后面位置的数已经后移到自身下一个位置了)

代码实现

void InsertSort(int* a, int n)//直接插入排序
{
	for (int i = 1; i < n; i++)
	{
		int end = i;//从第二个位置开始
		int tmp = a[end];//先保存这个值
		while (end > 0)
		{
			if (tmp < a[end - 1])
			{
				a[end] = a[end - 1];
				end--;
			}
			else
			{
				break;//如果不符合,就直接退出了
			}
		}
		a[end] = tmp;
	}
}

易错点:要使用 tmp 与前面的各个值进行依次比较(不能使用 a[end] ),因为 end 的值一直在变。每次插入都只能将一个数插入到原来的序列中,而插入的数就是这个 tmp。

复杂度分析

在最坏情况下,每趟都要比较 ‘满’,那么从第二个开始,就要依次比较 1 2 3 4 … n ,累加得:量级为 N^2。但在最好情况下(有序),这个人排序只需要遍历一次就可以完成排序了,量级为 N,所以在这个序列接近有序的时候,直接插入排序的效率可以接近O(N)
插入排序没有开额外的空间。并且从后往前按顺序排,遇到等于的就停下,所以这个排序很稳定。
时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定

希尔排序

插入排序是一个非常好的排序,特别是在序列接近有序的情况下,效率甚至可以达到接近 O(N),那么如何能设计一个算法先对数据先进行预排序,使序列在整体进行插入排序之前能够达到一个接近有序的状态呢?

希尔排序
希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后,取,重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。

具体步骤就是将这个数据分为多组,每组成员之间间隔 gap个数据,每组进行插入排序,这样可以使小的数尽量在前面,大的数尽量在后面;然后使 gap按规模递减,重复上面的步骤,最后当gap等于1的时候,就是直接插入排序,并且此时的序列已经是非常接近有序的状态了。
在这里插入图片描述

代码实现

第一种,分组,对每一组进行分别排序。

void ShellSort(int* a, int n)//希尔排序
{
	int gap = n / 3;
	while (gap >= 1)
	{
		for (int z = 0; z < gap; z++)//gap组数据
		{
			for (int i = z; i < n - gap; i += gap)//对一组进行直接插入排序
			{
				int end = i;
				int tmp = a[end + gap];
				for (int j = end; j < n-gap; j += gap)
				{
					while (end>=0)
					{
						if (tmp < a[end])
						{
							a[end + gap] = a[end];
						}
						else
						{
							break;
						}
						end -= gap;
					}
					a[end + gap] = tmp;
				}

			}
		}
		gap /= 2;//调整gap的值
	}
}

特点:思路较为简单,但循环较多,代码较复杂。

第二种,分组,但整体顺序是从头开始依次往下,插入排序的时候每次跳过 gap 个数据。

void ShellSort(int* a, int n)//希尔排序
{
	int gap = n / 3;
	while (gap >= 1)
	{
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			for (int j = end; j < n-gap; j += gap)
			{
				while (end>=0)
				{
					if (tmp < a[end])
					{
						a[end + gap] = a[end];
					}
					else
					{
						break;
					}
					end -= gap;
				}
				a[end + gap] = tmp;
			}

		}
		gap /= 2;  
	}
}

初学者不好思考,但是理解之后代码更简单好控制,不易出错。

复杂度分析
时间复杂度:O(N^1.3) 接近于O(N*logN)
空间复杂度:O(1)
稳定性:不稳定

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

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

相关文章

[中间件~大厂面试题] 腾讯三面,40亿的QQ号如何去重

前言&#xff1a; 在Spring Boot框架下&#xff0c;可以使用以下方法来去重40亿个QQ号.请注意&#xff1a;QQ号码的理论最大值为 2 32 − 1 2^{32} - 1 232−1&#xff0c;大概是43亿左右。 文章目录 提前总结(总分总&#xff5e;&#xff5e;&#xff5e;)最粗鲁的方式1. 使用…

深入理解Linux网络笔记(二):内核和用户进程协作之阻塞方式

本文为《深入理解Linux网络》学习笔记&#xff0c;使用的Linux源码版本是3.10&#xff0c;网卡驱动默认采用的都是Intel的igb网卡驱动 Linux源码在线阅读&#xff1a;https://elixir.bootlin.com/linux/v3.10/source 2、内核是如何与用户进程协作的&#xff08;一&#xff09; …

疯 狂 的 文 件 夹 【收藏起来】

文章目录 &#x1f4c1;故事的开始&#x1f4c1;一起疯狂&#x1f4da;资源领取 专栏Python零基础入门篇&#x1f525;Python网络蜘蛛&#x1f525;Python数据分析Django基础入门宝典&#x1f525;小玩意儿&#x1f525;Web前端学习tkinter学习笔记Excel自动化处理 &#x1f4…

力扣-345.反转字符串中的元音字母

Idea 将s中的元音字母存在字符串sv中&#xff0c;并且使用一个数组依次存储元音字母的下标。 然后将字符串sv进行反转&#xff0c;并遍历元音下标数组&#xff0c;将反转后的字符串sv依次插入到源字符串s中 AC Code class Solution { public:string reverseVowels(string s) {…

力扣 -- 1049. 最后一块石头的重量 II(01背包问题)

参考代码&#xff1a; 未优化代码&#xff1a; class Solution { public:int lastStoneWeightII(vector<int>& stones) {int nstones.size();int sum0;for(const auto& e:stones){sume;}int aimsum/2;//多开一行&#xff0c;多开一列vector<vector<int&g…

排序---P1116 车厢重组

P1116 车厢重组 来自 <车厢重组 - 洛谷> 其实这道题本质上就是求逆序对的过程&#xff1a; 两种方法&#xff1a;一个是通过冒泡排序过程求逆序对&#xff1b;一个是通过归并排序过程求逆序对。 法一&#xff1a;当通过冒泡排序进行正序排列时&#xff0c;相邻两个数需要…

批量将文件名称符合要求的文件自动复制到新文件夹:Python实现

本文介绍基于Python语言&#xff0c;读取一个文件夹&#xff0c;并将其中每一个子文件夹内符合名称要求的文件加以筛选&#xff0c;并将筛选得到的文件复制到另一个目标文件夹中的方法。 本文的需求是&#xff1a;现在有一个大的文件夹&#xff0c;其中含有多个子文件夹&#x…

Redis与分布式-集群搭建

接上文 Redis与分布式-哨兵模式 1. 集群搭建 搭建简单的redis集群&#xff0c;创建6个配置&#xff0c;开启集群模式&#xff0c;将之前配置过的redis删除&#xff0c;重新复制6份 针对主节点redis 1&#xff0c;redis 2&#xff0c;redis 3都是以上修改内容&#xff0c;只是…

C++位图—布隆过滤器

目录 位图概念位图应用 布隆过滤器简介布隆过滤器的优缺点布隆过滤器应用场景布隆过滤器实现布隆过滤器误判率分析 总结 位图概念 位图是一种数据结构&#xff0c;用于表示一组元素的存在或不存在&#xff0c;通常用于大规模数据集的快速查询。它基于一个位数组&#xff08;或位…

管理经济学基本概念(二): 规模经济、需求曲线、供给曲线等

1、关键术语 1.1、边际报酬递减规律 边际报酬递减规律是指随着产出量的扩大&#xff0c;边际生产率(与增量投入要素相联系的增量产出量)最终会下降。 递增的边际生产率意味着边际成本递增。 递增的边际成本最终导致平均成本递增。 1.2、规模经济 (1) 如果长期平均成本相对…

打开泰坦陨落2找不到msvcp120.dll无法执行代码/msvcr120.dll丢失修复方法

msvcp120.dll 是 Windows 操作系统中的一个动态链接库文件&#xff0c;对于许多程序和游戏的运行起着至关重要的作用。然而&#xff0c;有时候我们可能会遇到 msvcp120.dll 丢失的情况&#xff0c;导致电脑出现各种问题。本文将详细介绍 msvcp120.dll 丢失的四种解决方法&#…

【项目】5.1阻塞和非阻塞、同步和异步 5.2Unix、Linux上的五种IO模型

5.1阻塞和非阻塞、同步和异步&#xff08;网络IO&#xff09; 典型的一次IO的两个阶段是什么&#xff1f;数据就绪和数据读写 数据就绪&#xff1a;根据IO操作的就绪状态 阻塞非阻塞 数据读写&#xff1a;根据应用程序和内核的交互方式 同步异步 陈硕&#xff1a;在处理IO的…

【小沐学Python】各种Web服务器汇总(Python、Node.js、PHP、httpd、Nginx)

文章目录 1、Web服务器2、Python2.1 简介2.2 安装2.3 使用2.3.1 http.server&#xff08;命令&#xff09;2.3.2 socketserver2.3.3 flask2.3.4 fastapi 3、NodeJS3.1 简介3.2 安装3.3 使用3.3.1 http-server&#xff08;命令&#xff09;3.3.2 http3.3.3 express 4、PHP4.1 简…

选择排序算法:简单但有效的排序方法

在计算机科学中&#xff0c;排序算法是基础且重要的主题之一。选择排序&#xff08;Selection Sort&#xff09;是其中一个简单但非常有用的排序算法。本文将详细介绍选择排序的原理和步骤&#xff0c;并提供Java语言的实现示例。 选择排序的原理 选择排序的核心思想是不断地从…

网络工程师怎么才算开窍

做网络工程师怎么样才算开窍&#xff1f;刚才有个朋友他说他希望从事网络工程师之后若干年。比如说当他到35岁的时候&#xff0c;他不希望出现跟今天现在是2023年&#xff0c;今年的这种裁员潮里面所遇到的那些主人公&#xff0c;就是技术学的也不错&#xff0c;然后工作也不错…

37 二叉树的最大深度

二叉树的最大深度 题解1 深度优先搜索&#xff08;递归弹栈&#xff09;题解2 广度优先搜索&#xff08;队列&#xff09; 给定一个二叉树 root &#xff0c;返回其最大深度。 二叉树的 最大深度 是指从根节点到最远叶子节点的最长路径上的节点数。 提示&#xff1a; 树中节点…

阿里云PolarDB自研数据库详细介绍_兼容MySQL、PostgreSQL和Oracle语法

阿里云PolarDB数据库是阿里巴巴自研的关系型分布式云原生数据库&#xff0c;PolarDB兼容三种数据库引擎&#xff1a;MySQL、PostgreSQL、Oracle&#xff08;语法兼容&#xff09;&#xff0c;目前提供云原生数据库PolarDB MySQL版、云原生数据库PolarDB PostgreSQL版和云原生数…

使用 Python 的多项 Logistic 回归问题

一、说明 多项逻辑回归是一种统计方法&#xff0c;用于预测两个以上类别的分类结果。当因变量是分类变量而不是连续变量时&#xff0c;它特别有用。 二、分类预测 在多项式逻辑回归中&#xff0c;模型预测属于因变量每个类别的观测值的概率。这些概率可以解释为观察结果属于每…

聊聊并发编程——原子操作类和Fork/Join框架

目录 原子操作类 实现原子性原理 保证原子性的方法 Fork/Join框架 分而治之 工作窃取算法 Fork/Join框架的设计 示例 原子操作类 线程A和线程B同时更新变量i进行操作i1,最后的结果可能i不等于3而是等于2。这是线程不安全的更新操作&#xff0c;一般我们会使用Synchron…

CCF CSP认证 历年题目自练Day18

CCF CSP认证 历年题目自练Day18 题目一 试题编号&#xff1a; 201809-1 试题名称&#xff1a; 卖菜 时间限制&#xff1a; 1.0s 内存限制&#xff1a; 256.0MB 问题描述&#xff1a; 问题描述   在一条街上有n个卖菜的商店&#xff0c;按1至n的顺序排成一排&#xff0c;这…