直接插入排序到底有多“直男”

news2024/11/16 10:47:32

作者主页:paper jie的博客_CSDN博客-C语言,算法详解领域博主

本文作者:大家好,我是paper jie,感谢你阅读本文,欢迎一建三连哦。

本文录入于《算法详解》专栏,本专栏是针对于大学生,编程小白精心打造的。笔者用重金(时间和精力)打造,将算法基础知识一网打尽,希望可以帮到读者们哦。

其他专栏:《系统解析C语言》《C语言》《C语言-语法篇》

内容分享:本期将对八大排序中的直接插入排序进行详细的讲解,各位看官姥爷快搬好小板凳坐好叭。

    -------- 不要998,不要98,只要一键三连,三连买不了吃亏,买不了上当

目录

前言

什么是直接插入排序

直接插入排序的实现

基本思想

具体代码

直接插入排序的原理

直接插入排序的特点和性能

复杂度 

稳定性

二分查找代码的应用


前言

上期我们对快速排序进行了分析,了解了它的思想,原理和实现代码及它的特性。今天我们来了解一下插入排序中的直接插入排序。

什么是直接插入排序

插入排序,一般也被称为直接插入排序。对于少量元素的排序,它是一个有效的算法 。插入排序是一种最简单的排序方法,它的基本思想是将一个记录插入到已经排好序的有序表中,从而一个新的、记录数增1的有序表。在其实现过程使用双层循环,外层循环对除了第一个元素之外的所有元素,内层循环对当前元素前面有序表进行待插入位置查找,并进行移动

直接插入排序的实现

基本思想

1.   每次从无序表中取出第一个元素,把它插入到有序表的合适位置,使有序表仍然有序。

2.   第一趟比较前两个数,然后把第二个数按大小插入到有序表中

3.   第二趟把第三个数据与前两个数从后向前扫描,把第三个数按大小插入到有序表中;

4.   依次进行下去,进行了(n-1)趟以后就完成了整个排序过程。

具体代码

#include <stdio.h>
//直接插入排序
void InsertSort(int* arr, int len)
{
	//定义变量用来循环
	int i = 0;
	int j = 0;
	//哨兵变量 即用来存放需要查入的元素
	int tmp = 0;
	//第一层循环 循环len-1次
	//因为当数组只有一个元素时它就是有序的不用比较
	//所以从第二个元素开始比较 即i=1
	for (i = 1; i < len; i++)
	{
		//将需要插入的元素放入tmp中
		tmp = arr[i];
		//第二层循环 和要插入的元素比较
		//要比较的就是插入元素前面的 即j=i-1
		for (j = i - 1; j >= 0; j--)
		{
			//如果插入元素前一个大于插入元素就将它们交换
			if (arr[j] > arr[j + 1])
			{
				arr[j + 1] = arr[j];
				arr[j] = tmp;
			}
			//如果不大于插入元素的时候就跳出
			//因为要插入元素前面的子数组的元素已经是有序的
			//只要大于子数组后面的元素,前面的就不用比较了
			else
				break;
		}
	}
}
int main()
{
	//待排序数组
	int arr[] = { 3,8,7,2,6,9,1,4 };
	//直接插入排序函数
	InsertSort(arr, sizeof(arr) / sizeof(arr[0]));
	//打印
	int i = 0;
	for (i = 0; i < sizeof(arr) / sizeof(arr[0]); i++)
	{
		printf("%d ", arr[i]);
	}

	return 0;
}

直接插入排序的原理

直接插入排序是由两层嵌套循环组成的。外层循环标识并决定待比较的趟术和数值。内层循环为待比较数值确定其最终位置。直接插入排序将待比较的数值与它的前一个数值进行比较,所以外层循环是从第二个数值开始的。当前一数值比待比较数值大的情况下继续循环比较,直到找到比待比较数值小的并将待比较数值置入其后一位置,结束该次循环。

这里我们以代码中的数组为例:我们将数组{ 3,8,7,2,6,9,1,4}进行升序。我们将3元素从无序表中拿出来放到有序表中,有序表中无元素,它仍然有序。注意(比较中是从后往前,比较的数组是有序的,如果待插入的元素大于比较元素,则比较元素前面的就不用比较了。)这时开始正式比较,第一次比较8大于3,不用交换直接插入,有序表3,8。第二次比较7小于8交换,7大于3不交换,直接插入,有序表3,7,8。第三次比较2小于8交换,2小于7交换,2小于3交换,前面没有元素了,插入。有序表2,3,7,8。第四次交换比较6小于8交换,6小于7交换,6大于3不交换,插入。有序表2,3,6,7,8。第五次交换比较9大于6不交换,直接插入。有序表2,3,6,7,8,9。第六次交换比较1小于9交换,1小于7交换,1小于6交换,1小于3交换,1小于2交换。有序表1,2,3,6,7,8,9。第7次交换比较4小于9交换,4小于8交换,4小于7交换,4小于6交换,4大于3不交换,直接插入,有序表1,2,3,4,6,7,8,9。这时数组就已经变成有序的了。

画图分析:

直接插入排序的特点和性能

复杂度 

直接插入排序的时间复杂度为 O (n^2) ,空间复杂度为 O (1) 。 在排序过程中,如果待排序的序列已经近似有序,则直接插入排序的效率会很高,因为少需移动已排序部分的元素。 但如果待排序序列的规模很大或者是随机分布的,那么直接插入排序的效果会不如其他高效率排序算法,如快速排序等。

稳定性

插入排序是在一个已经有序的小序列的基础上,一次插入一个元素。如果碰见一个和插入元素相等的,那么将会把待插入元素放在相等元素的后面。所以,相等元素的相对的前后顺序没有改变,所以插入排序是稳定的。

二分查找代码的应用

下面还有一个插入排序中的二分查找,大家可以看看


#include<cstdio>
#include<cstdlib>
#include<cstring>
#include<cmath>
#include<algorithm>
#include<iostream>
#define MaxSize 100
#define ElemType int
#define Status int
using namespace std;
//顺序表数据结构
typedef struct
{
	ElemType data[MaxSize];//顺序表元素
	int length;            //顺序表当前长度
}SqList;
//***************************基本操作函数*******************************//
//初始化顺序表函数,构造一个空的顺序表 
Status InitList(SqList &L)
{
	memset(L.data,0,sizeof(L));//初始化数据为0
	L.length=0;                //初始化长度为0
	return 0;
}
//创建顺序表函数 初始化前n个数据
bool CreatList(SqList &L,int n)
{
	if(n<0||n>MaxSize)false;//n非法
	for(int i=0;i<n;i++)
	{
		scanf("%d",&L.data[i]);
		L.length++;
	}
	return true;
}
//插入函数 位置i插入数据 i及之后元素后移  1=<i<=length+1 
bool InsertList(SqList &L,int i,ElemType e)
{
	if(i<1||i>L.length+1) //判断位置是否有效
     {
		printf("位置无效!!!\n");
    	return false;
	 }
	if(L.length>=MaxSize)//判断存储空间是否已满
	{
		printf("当前存储空间已满!!!\n");
		return false;
	}
	for(int j=L.length;j>=i;j--)//位置i及之后元素后移
	{
		L.data[j]=L.data[j-1];
	}
	L.data[i-1]=e;
	L.length++;
	return true;
}
//删除函数 删除位置i的元素 i之后的元素依次前移
bool  ListDelete(SqList &L,int i)
{
	if(i<1||i>L.length)
     {
		printf("位置无效!!!\n");
    	return false;
	 }
	for(int j=i;j<=L.length-1;j++)//位置i之后元素依次前移覆盖
	{
		L.data[j-1]=L.data[j];
	}
	L.length--;
	return true;
}
//查找函数 按位置从小到大查找第一个值等于e的元素 并返回位置
int LocateElem(SqList L,ElemType e)
{
 for(int i=0;i<L.length;i++)//从低位置查找
	{
		if(L.data[i]==e)
			return i+1;
	}
 return 0;
 
}
//二分查找函数
int Binary_search(SqList L,ElemType key)
{
	int low = 0;int mid = 0;int high = L.length-1;
	while(low<=high)
	{
		mid = (low+high)/2;
 		if(key==L.data[mid])
		{
			return mid;
		}
		else if(key>L.data[mid])
		{
			low = mid+1;
		}
		else
		{
			high = mid-1;
		}
	}
	return -1;
}
//********************************功能函数*****************************************//
//输出功能函数 按位置从小到大输出顺序表所有元素
void PrintList(SqList L)
{
	printf("当前顺序表所有元素:");
	for(int i=0;i<L.length;i++)
	{
		printf("%d ",L.data[i]);
	}
	printf("\n");
}
//创建顺序表函数
void Create(SqList &L)
{
	int n;bool flag;
	printf("请输入要创建的顺序表长度(>1):");
	scanf("%d",&n);
	printf("请输入%d个数(空格隔开):",n);
	flag=CreatList(L,n);
	if(flag){
		printf("创建成功!\n");
		PrintList(L);
	}
	else printf("输入长度非法!\n");
 
}
//插入功能函数 调用InsertList完成顺序表元素插入 调用PrintList函数显示插入成功后的结果
void Insert(SqList &L)
{
  int place;ElemType e;bool flag;
  printf("请输入要插入的位置(从1开始)及元素:\n");
  scanf("%d%d",&place,&e);
  flag=InsertList(L,place,e);
  if(flag) 
  {
	printf("插入成功!!!\n");
	PrintList(L);
  }
}
//删除功能函数 调用ListDelete函数完成顺序表的删除 调用PrintList函数显示插入成功后的结果
void Delete(SqList &L)
{
  int place;bool flag;
  printf("请输入要删除的位置(从1开始):\n");
  scanf("%d",&place);
  flag=ListDelete(L,place);
  if(flag) 
  {
	printf("删除成功!!!\n");
	PrintList(L);
  }
}
//查找功能函数 调用LocateElem查找元素
void Search(SqList L)
{
  ElemType e;int flag;
  printf("请输入要查找的值:\n");
  scanf("%d",&e);
  flag=LocateElem(L,e);
  if(flag) 
  {
	printf("该元素位置(从1起)为:%d\n",flag);
  }
  else
	  printf("未找到该元素!\n");
}
//简单选择排序功能函数 为二分做准备
void SelectSort(SqList &L)
{
	int min;int temp;
	for(int i=0;i<L.length;i++)
	{
		min=i;
		for(int j=i+1;j<L.length;j++)
		{
			if(L.data[j]<L.data[min])min=j;
		}			
		if(min!=i)
		{
			temp=L.data[min];
			L.data[min]=L.data[i];
			L.data[i]=temp;
		}
	}
}
//二分查找功能函数 调用Binary_search
void Binary(SqList L)
{
	int key;int place;
	SelectSort(L);       //二分查找前先排序
	PrintList(L);
	printf("请输入要查找的值:\n");
	scanf("%d",&key);
	place=Binary_search(L,key);
	if(place>=0)printf("位置(从0起)为:%d\n",place);
	else printf("未找到!\n");
}
//菜单
void menu()
{
   printf("********1.创建    2.插入*********\n");
   printf("********3.删除    4.查找*********\n");
   printf("********5.输出    6.二分查找*********\n");
   printf("********7.退出\n");
}
int main()
{
 SqList L;int choice;
 InitList(L);
 while(1)
 {
  menu();
  printf("请输入菜单序号:\n");
  scanf("%d",&choice);
  if(7==choice) break;
  switch(choice)
  {
  case 1:Create(L);break;
  case 2:Insert(L);break;
  case 3:Delete(L);break;
  case 4:Search(L);break;
  case 5:PrintList(L);break;
  case 6:Binary(L);break;
  default:printf("输入错误!!!\n");
  }
 }
 return 0;
}

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

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

相关文章

JavaScript中的垃圾回收和内存泄漏

垃圾回收 JavaScript 中的内存管理是自动执行的&#xff0c;而且是不可见的。我们创建基本类型、对象、函数……所有这些都需要内存。 当不再需要某样东西时会发生什么? JavaScript 引擎是如何发现并清理它? 垃圾回收有两种方法&#xff1a;标记清除、引用计数。引用计数不…

95后很狂阿里P7晒出工资单:狠补了两眼泪汪汪,真香...

最近一哥们跟我聊天装逼&#xff0c;说他最近从阿里跳槽了&#xff0c;我问他跳出来拿了多少&#xff1f;哥们表示很得意&#xff0c;说跳槽到新公司一个月后发了工资&#xff0c;月入5万多&#xff0c;表示很满足&#xff01;这样的高薪资着实让人羡慕&#xff0c;我猜这是税后…

便携式AIS接收机dAI01

1.设备简介 AIS是指船舶自动识别系统&#xff08;Automatic Identification System&#xff09;&#xff0c;船舶上有AIS收发机&#xff0c;AIS收发机会把船舶通过GPS定位获取到的本船的位置、速度等动态信息和船舶自己的船号、长宽等静态信息广播发射出去&#xff0c;其他用户…

雷达人体感应器成品,家居办公场景探测联动,智能化雷达感知技术应用

随着智能数据和人工智能的日益普及&#xff0c;越来越多的智能硬件设备得以推广和应用到日常生活中。 智能人体存在感应器是这一类智能硬件设备中非常有代表性的一种&#xff0c;它可以被应用在家居、办公等场景中&#xff0c;在很大程度上&#xff0c;它为我们的生活提供了很…

Liunx 安装、卸载Mysql,远程连接

Liunx 安装、卸载Mysql 一、 卸载mysql 查看mysql安装情况 rpm -qa | grep -i mysql删除上图中所有信息 rpm -ev mysql-community-release-el7-5.noarch --nodeps再次查询&#xff0c;没有数据&#xff0c;则为删除干净 find / -name mysqlrm -rf /var/lib/mysql 将机器上…

Java版企业工程管理系统源代码Spring Boot + 二次开发 + 前后端分离

工程项目各模块及其功能点清单 一、系统管理 1、数据字典&#xff1a;实现对数据字典标签的增删改查操作 2、编码管理&#xff1a;实现对系统编码的增删改查操作 3、用户管理&#xff1a;管理和查看用户角色 4、菜单管理&#xff1a;实现对系统菜单的增删改查操…

使用python编程数学建模-常见excel数据使用python以行的方式按需读取

读取原始数据 首先导入pandas库   接着使用pandas库里面的read_csv方法来读取我们的文件&#xff0c;由于数据文件和程序文件是在统一目录下&#xff0c;因此无需使用绝对路径 import pandas as pd data1 pd.read_csv("data1.csv")读取数据的前20行数据 这里我们…

RTC time和Local time区别以及Linux 设置时区和修改时间

RTC time和Local time 在Linux系统中存在两个时钟时间&#xff0c;分别是 硬件时钟RTC&#xff08;Real Time Clock&#xff09; 系统时钟&#xff08;System Clock&#xff09;硬件时钟是指的在主板上的时钟设备&#xff0c;也就是通常可以在BIOS画面设置的时钟&#xff0c;即…

魏副业而战:怎么提升自己做项目的能力?

我是魏哥&#xff0c;与其在家躺平&#xff0c;不如魏副业而战&#xff01; 昨天分享了老李做的拉新项目&#xff0c;很多小伙伴留言。 有人说&#xff0c;制作100个视频蛮难的&#xff1b; 有人说&#xff0c;发布100个视频最后留下4个&#xff0c;这对人的考验蛮大的&…

JDK8新特性之lambda表达式

&#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 接下来看看由辉辉所写的关于lambda表达式的相关操作吧 目录 &#x1f973;&#x1f973;Welcome Huihuis Code World ! !&#x1f973;&#x1f973; 一.是什么 二.为什么要用 三.底层…

【资料分享】Xilinx Zynq-7010/7020工业核心板规格书(双核ARM Cortex-A9 + FPGA,主频766MHz)

1 核心板简介 创龙科技SOM-TLZ7x是一款基于Xilinx Zynq-7000系列XC7Z010/XC7Z020高性能低功耗处理器设计的异构多核SoC工业核心板&#xff0c;处理器集成PS端双核ARM Cortex-A9 PL端Artix-7架构28nm可编程逻辑资源&#xff0c;通过工业级B2B连接器引出千兆网口、USB、CAN、UA…

Linux发展史和Linux系统安装

Linux发展史和Linux系统安装 Linux发展史Linux前身-UnixLinux诞生开源文化Linux系统特点Linux分支 Linux系统的安装安装方式虚拟机软件虚拟机的安装VMware Workstation的安装Virtual Box的安装 Linux版本的选择新建虚拟机选择镜像文件安装使用VMware Workstation Linux操作系统…

【总结】yarn ResourceManager 宕机重启总是失败解决排查

目录 Yarn ResourceManager 莫名奇妙宕机重启Yarn ResourceManager 报错1重启Yarn ResourceManager 报错2成功解决 Yarn ResourceManager 莫名奇妙宕机 接到同事反馈&#xff0c;说yarn RM 端口总是访问超时。但是查看日志&#xff0c;又没有发现任务蛛丝马迹&#xff0c;且RM…

ChatGPT扇动翅膀后带来的蝴蝶效应

对于蝴蝶效应最常见的阐述是&#xff1a;“一只南美洲亚马逊河流域热带雨林中的蝴蝶&#xff0c;偶尔扇动几下翅膀&#xff0c;可以在两周以后引起美国得克萨斯州的一场龙卷风。” 简介肯尼亚essay 正文论文代写之都为什么是肯尼亚?蝴蝶效应 简介 在印象中贫穷且落后的东非国家…

小航助学2023年6月GESP_C++一级试卷(含题库答题软件账号)

需要在线模拟训练的题库账号请点击 小航助学编程在线模拟试卷系统&#xff08;含题库答题软件账号&#xff09;_程序猿下山的博客-CSDN博客 删除编辑附件图文 答案:A 第1题以下不属于计算机输出设备的有&#xff08; &#xff09;。 A、麦克风B、音箱C、打印机D、显示器 答…

【Kubernetes部署篇】Kubeadm方式搭建K8s集群 1.27.0版本

文章目录 一、集群规划及架构二、系统初始化准备(所有节点同步操作)三、安装并配置cri-dockerd插件四、安装kubeadm(所有节点同步操作)五、初始化集群六、Node节点添加到集群七、安装网络组件Calico八、测试CoreDNS解析可用性 一、集群规划及架构 官方文档&#xff1a; 二进制…

低代码开发平台魔笔,评测火热征集!

阿里云低代码开发平台魔笔是一款面向全端&#xff08;Web、H5、全平台小程序、App&#xff09;场景&#xff0c;模型驱动的低代码开发平台&#xff0c; 具有集成开放、一云多端、多云部署等优势&#xff0c;助力客户在数字化转型进程中真正实现降本增效。 即日起至7月31日&…

自学网络安全遇到问题怎么解决?

趁着今天下班&#xff0c;我花了几个小时整理了下&#xff0c;非常不易&#xff0c;希望大家可以点赞收藏支持一波&#xff0c;谢谢。 我的经历&#xff1a; 我 19 年毕业&#xff0c;大学专业是物联网工程&#xff0c;我相信很多人在象牙塔里都很迷茫&#xff0c;到了大三大…

Xilinx XCZU7EV评估板规格书(四核ARM Cortex-A53 + 双核ARM Cortex-R5 + FPGA,主频1.5GHz)

1 评估板简介 创龙科技TLZU-EVM是一款基于Xilinx UltraScale MPSoC系列XCZU7EV高性能处理器设计的高端异构多核SoC评估板&#xff0c;处理器集成PS端&#xff08;四核ARM Cortex-A53 双核ARM Cortex-R5&#xff09; PL端UltraScale架构可编程逻辑资源&#xff0c;支持4K60fp…

Docker学习笔记4

使用docker管理容器&#xff1a; 理解下容器、镜像、仓库、docker daemon和docker client三者之间的关系&#xff1a; 总结&#xff1a; 1&#xff09;docker客户端下达命令docker daemon。 2&#xff09;docker daemon 先到本地镜像目录查找容器&#xff0c;如果没有&#…