排序【插入排序】

news2024/12/23 18:40:35

排序的概念

排序:所谓排序,就是将一份数据,通过某个或者某些关键字的大小,进行递增或者递减排序的操作。

稳定性:假定在待排序的数据组中,存在多个相同的元素,若经过排序,这些数据之间的相对位置应保持不变。例如:在原数组中,a[i]=a[j],并且a[i]的位置在a[j]之前,如果这个数组被进行了排序操作,且a[i]仍然在a[j]之前(a[i]a[j]的位置可能会被改变,但是他们之间的位置关系不会改变),那么这个排序算法就是稳定的,反之就是不稳定。

内部排序:数据元素全部在内存中的排序。

外部排序:由于数据元素太多,不能同时放在内存中,根据排序过程的需求,不断地在内外存之间移动数据的排序。

常见的算法排序

在这里插入图片描述

插入排序算法的实现

基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的元素根据其元素的大小逐个插入到一个已经排好序的有序序列中,所有元素插入完为止,这样就得到一个新的有序序列。

就是将待排序元素之前的数组当作已经有序的数组,再将待排元素与数组内的元素进行比较。

在我们玩扑克牌的时候,就在无意中使用了插入排序的思想在这里插入图片描述

直接插入排序:

当插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序了,这时候用array[i]与array[i-1],array[i-2],…进行比较,找到插入位置,就将array[i]插入,原来位置上的元素顺序后移,如图在这里插入图片描述
直接插入排序的总结:

  1. 元素集合越接近有序,直接插入排序算法就越快
  2. 时间复杂度为 O ( N 2 ) O(N^2) O(N2)
  3. 空间复杂度为 O ( 1 ) O(1) O(1),它是一种稳定的排序算法

代码

#include<stdio.h>

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		//[0, end]有序,将end+1位置的值插入到[0, end]里面去,并保持有序
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		//这个代码在这里可以同时解决俩个情况
		// 情况一:tmp在遍历的时候发现了比他更小的值
		// 情况二:遍历了一边数组,并没有发现比tmp更小的数(end < 0)
		a[end + 1] = tmp;
	}
}

void PrintArray(int* a, int n)
{
	for (int i = 0; i < n; i++)
	{
		printf("%d ", a[i]);
	}
	printf("\n");
}


void TestInsertSort()
{
	int a[] = { 9,8,6,4,2,1,0,5,7,3 };
	InsertSort(a,sizeof(a)/sizeof(a[0]));
	PrintArray(a, sizeof(a) / sizeof(a[0]));

}

在这里插入图片描述

直接插入排序遇到逆序数组就会很慢了,这时就有个叫希尔的人对直接插入排序进行了优化,这使得排序效率大大提升了。

希尔排序

希尔排序在排序之前会进行预排序,让数组接近有序,然后再使用直接插入排序。
在这里插入图片描述
上图为案例

我将数据分割成多个组,间隙为gap个(并不是在物理上分成多个数组,而是逻辑上将他们分组)。

假设gap为3,那么在分组中元素9的下一个元素为5,再下一个元素为8,最后一个元素为5,逻辑上这个数组就为[9,5,8,5]
逻辑上以1开头的数组为[1,7,6],以2开头的数组为[2,4,3]
在这里插入图片描述
但是他们实际位置并没有改变,我们也没有开辟新空间来存放数据
我们分好组后,对每组元素进行插入排序,就是分别对[9,5,8,5][1,7,6]2,4,3进行内部的插入排序
在这里插入图片描述
经过预排序后原数组[9,1,2,5,7,4,8,6,3,5]变成了[5,1,2,5,6,3,8,7,4,9]

预排序并没有将整个数组变成有序,而是将每个间隙为gap的数组变成了有序(我们使用还是直接插入排序,只不过元素与元素之间的间隔不是 1,而是gap)。

虽然预排序没有直接的将整个数组排好序,但是他能很快速的将较大的元素往后放,把较小的数据往前放(案例数组经过预排序后,最后的三个数据就是每组最大的元素)

单组排序

我们先来红色这一组([9,5,8,5]

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

在这里插入图片描述
排序后正如我们所想的一样,[9,5,8,5]这一组已经有序了。

接下来就是从单组排序拓展到多组排序了

单组排序到多组排序

有两种方法

  1. 在外面再套一层循环(每组分开排序)
void ShellSort(int* a, int n)
{
	
	int gap = 3;
	for (int j = 0; j < gap; j++)//j确定起始位置
	{
		for (int i = 0; i < n - gap; i += gap)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}

}

效果:
在这里插入图片描述

  1. 多组并在一起排序
    改动也很简答,将for (int i = 0; i < n - gap; i += gap)改成for (int i = 0; i < n - gap; i++)
void ShellSort(int* a, int n)
{
	int gap = 3;
	for (int i = 0; i < n - gap; i++)
	{
		int end = i;
		int tmp = a[end + gap];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + gap] = a[end];
				end -= gap;
			}
			else
			{
				break;
			}
		}
		a[end + gap] = tmp;
	}

}

效果:
在这里插入图片描述

他们的效率是一样,只不过第二种方法更美观。

接下来就是改变gap的大小了。

改变gap并完成排序

gap大与小的区别

  • gap越大,大的数可以越快的跳到后面,小的数可以越小的跳到前面,但是预排序完了也越不接近有序。
  • gap越小,跳的越慢,但是也越接近有序;当gap等于1,就相当于直接插入排序了。

当gap等于1,那么这个数组就有序了。

那么这个gap该怎么变呢,其实到现在都没有一个准确的最优方法。

我们当前最合适的方法是 gap/3,但是为了避免gap=0,我们在后面+1也就是gap = gap / 3 + 1;

当gap>1时,是预排序,当gap==1时,是直接插入排序,并不是先通过一个函数完成预排序再通过另一个函数完成直接插入排序。

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

}

在这里插入图片描述
完整代码:

void ShellSort(int* a, int n)
{
	int gap = n;
	while (gap > 1)
	{
		gap = gap / 3 + 1;
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
		printf("gap=%2d:->", gap);
		PrintArray(a, n);
	}

}
void TestShellSort()
{
	int a[] = { 9,1,2,5,7,4,8,6,3,5 };
	printf("排序前:");
	PrintArray(a, sizeof(a) / sizeof(a[0]));
	ShellSort(a, sizeof(a) / sizeof(a[0]));
	printf("排序后:");
	PrintArray(a, sizeof(a) / sizeof(a[0]));
}

int main()
{
	TestShellSort();
	return 0;
}

结语

最后感谢您能阅读完此片文章,如果有任何建议或纠正欢迎在评论区留言,也可以前往我的主页看更多好文哦(点击此处跳转到主页)。
如果您认为这篇文章对您有所收获,点一个小小的赞就是我创作的巨大动力,谢谢!!!

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

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

相关文章

【论文阅读】transformer及其变体

写在前面&#xff1a; transformer模型已经是老生常谈的一个东西&#xff0c;以transformer为基础出现了很多变体和文章&#xff0c;Informer、autoformer、itransformer等等都是顶刊顶会。一提到transformer自然就是注意力机制&#xff0c;变体更是数不胜数&#xff0c;一提到…

【ARM】Ulink不同的系列对于芯片的支持和可以支持keil软件

【更多软件使用问题请点击亿道电子官方网站】 1、 文档目标 了解不同版本的ULINK可以支持的芯片架构&#xff0c;和ULINK可以和哪个系列的keil软件进行在线调试 2、 问题场景 用于了解不同ULINK仿真器对于芯片的支持是不一样的&#xff0c;并不是ULINK可以支持所有的keil软件…

搭建Renesas R7FA8D1BHECBD-BTB的开发调试环境(DAP-LINK: N32G45XVL-STB)

目录 概述 1 软硬件 1.1 软硬件环境信息 1.2 开发板信息 1.3 调试器信息 2 FSP和KEIL产生测试项目 2.1 FSP生成项目 2.2 Keil中配置 3 硬件连接框图 4 一个测试案例 4.1 功能介绍 4.2 定时器函数 5 测试 搭建Renesas R7FA8D1BHECBD-BTB的开发调试环境&#xff08…

学会python——在Excel中生成图表数据(python实例十五)

目录 1.认识Python 2.环境与工具 2.1 python环境 2.2 Visual Studio Code编译 3.生成表格数据 3.1 代码构思 3.2 代码示例 4.绘制图表 4.1 代码构思 4.2 代码示例 5.总结 1.认识Python Python 是一个高层次的结合了解释性、编译性、互动性和面向对象的脚本语言。 P…

《概率论与数理统计》期末笔记_下

目录 第4章 随机变量的数字特征 4.1 数学期望 4.2 方差 4.3 常见分布的期望与方差 4.4 协方差与相关系教 第5章 大数定律和中心极限定理 5.1 大数定律 5.2 中心极限定理 第6章 样本与抽样分布 6.1 数理统汁的基本概念 6.2 抽样分布 6.2.1 卡方分布 6.2.2 t分布 6.…

window搭建git环境

1.下载安装window下git专用软件scm 从Git for Windows 官网网站下载&#xff0c;并且一路安装即可 安装成功后通过桌面快捷图标Git Bash点击打开 安装后软件应该会自动帮助配置环境变量&#xff0c;如果没有需要自己配置使用 2.git环境配置 2.1设置姓名和邮箱(github上你注…

006-GeoGebra基础篇-GeoGebra划定区域导出gif动图

上一篇末尾放了一个成果展示&#xff0c;有朋友问客F怎么用GeoGebra导出gif动画&#xff0c;也好插入到笔记里或者直接放到PPT里&#xff08;插入PPT有专门教程&#xff0c;可以看003&#xff09;&#xff0c;本篇主要来介绍一下gif导出操作 这里写目录标题 一、成品展示二、操…

19.异常处理

学习知识&#xff1a;方法中&#xff0c;异常的抛出和捕获 Main.java&#xff1a; public class Main {public static void main(String[] args) {errtest errtest new errtest();try{errtest.testerr();} catch (ArithmeticException e) {System.out.println("这个方法…

BLACKBOX.AI:解锁编程学习新纪元,加速开发的AI得力助手

文章目录 &#x1f4af;BLACKBOX.AI 官网&#x1f341;1 BLACKBOX.AI 工具使用教程&#x1f341;2 BLACKBOX.AI工具使用界面介绍&#x1f341;3 Chat(聊天)功能&#x1f341;4 Explore (探索)功能&#x1f48e;4.1 Terminal(终端)功能&#x1f48e;4.2 Discover(发现)功能&…

追觅科技25届校招校招24年社招科技北森题库商业推理综合测评答题攻略、通关技巧

一、追觅科技这家公司怎么样&#xff1f; 追觅科技是一家在智能清洁家电领域表现出色的企业。 二、追觅科技待遇怎么样 追觅科技的待遇在业内具有竞争力&#xff0c;具体信息如下&#xff1a; 1. **薪酬结构**&#xff1a;根据对外经济贸易大学招生就业处发布的2023届校园招…

web安全渗透测试十大常规项(一):web渗透测试之Fastjson反序列化

渗透测试之Java反序列化 1. Fastjson反序列化1.1 FastJson反序列化链知识点1.2 FastJson反序列化链分析1.3.1 FastJson 1.2.24 利用链分析1.3.2 FastJson 1.2.25-1.2.47 CC链分析1.3.2.1、开启autoTypeSupport:1.2.25-1.2.411.3.2.2 fastjson-1.2.42 版本绕过1.3.2.3 fastjson…

VS2019+QT5.12.10: error MSB4036: 未找到“Join”任务。请检查下列各项: 1.) 项目文件中的任务名

1、背景 两个VS2019打开两个相同的项目&#xff0c;一个里可以正常运行&#xff0c; 一个中一直报错&#xff0c;&#xff0c;报的错也是瞎几把报的。。 2、重新安装插件 之前在VS的扩展中在线安装了qt插件&#xff0c; 安装了一半&#xff0c;比较慢&#xff0c;直接强行退出…

论文工具使用---connected papers

如何使用connected papers 使用方法具体功能其他资源 官网地址&#xff1a;connected papers &#xff1a;一个旨在帮助科研工作者快速搜索文献的全新工具&#xff0c;可以清晰的查看文献的引文信息&#xff0c;了解文献的引用和被引用关联。 使用方法 输入论文标题后&#xf…

Python逻辑控制语句 之 判断语句--石头剪刀布案例

需求&#xff1a; 1. 从控制台输入要出的拳 —— 石头&#xff08;1&#xff09;&#xff0f;剪刀&#xff08;2&#xff09;&#xff0f;布&#xff08;3&#xff09; 2. 电脑随机出拳 —— 先假定电脑只会出石头&#xff0c;完成整体代码功能 3. 比较胜负 胜负规则&#x…

项目训练营第六天

项目训练营第六天 前端注册界面开发 1、基本布局 将登录界面文件夹复制一份&#xff0c;粘贴到上一层目录User目录下&#xff0c;改名为Register 在typings.d.ts文件中添加如下的登录前端接口函数标准参数 以及返回值类型 2、接口开发 在api.ts中修改原先接口如下&…

Django 自定义过滤器

1&#xff0c;编写自定义过滤器并注册 创建目录 Test/app5/templatetags 分别创建文件 Test/app5/templatetags/__init__.py Test/app5/templatetags/myfilter.py 添加过滤器脚本 Test/app5/templatetags/myfilter.py from django import template register template.…

计算机毕业设计PyFlink+Spark+Hive民宿推荐系统 酒店推荐系统 民宿酒店数据分析可视化大屏 民宿爬虫 民宿大数据 知识图谱 机器学习

本科毕业设计(论文) 开题报告 学院 &#xff1a; 计算机学院 课题名称 &#xff1a; 民宿数据可视化分析系统的设计与实现 姓名 &#xff1a; 庄贵远 学号 &#xff1a; 2020135232 专业 &#xff1a; 数据科学与大数据技术 班级 &#xff1a; 20大数据本科2…

Linux开发讲课28---Linux USB 设备驱动模型

Linux 内核源码&#xff1a;include\linux\usb.h Linux 内核源码&#xff1a;drivers\hid\usbhid\usbmouse.c 1. BUS/DEV/DRV 模型 "USB 接口"是逻辑上的 USB 设备&#xff0c;编写的 usb_driver 驱动程序&#xff0c;支持的是"USB 接口"&#xff1a; US…

63.ThreadLocal原理

JDK8中ThreadLocal的设计 每个Thread维护一个ThreadLocalMap,这个map的key是ThreadLocal实例本身,value才是真正要存储的值Object。 Thread -> ThreadLocalMap -> <ThreadLocal实例对象, 变量副本> jdk早期设计 ThreadLocal -> ThreadLocalMap -> <T…

6.优化算法之模拟

1.替换所有的问号 . - 力扣&#xff08;LeetCode&#xff09; class Solution {public String modifyString(String s) {char[] sss.toCharArray();int nss.length;for(int i0;i<n;i){if(ss[i]?){for(char cha;ch<z;ch){if((i0||ss[i-1]!ch)&&(in-1||ss[i1]!c…