【数据结构】排序之插入排序

这篇具有很好参考价值的文章主要介绍了【数据结构】排序之插入排序。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

1.前言

在生活中处处可见排序,当我们打开京东或者其它购物平台时,搜索物品,它会有一定的排序。
这次就来分享的博客与排序有关。
正文开始。

2. 排序的概念及其运用

2.1 排序的概念

排序:所谓排序,就是使一串记录,按照其中的某个或某些关键字的大小,递增或递减的排列起来的操作。

稳定性:假定在待排序的记录序列中,存在多个具有相同的关键字的记录,若经过排序,这些记录的相对次序保持不变,即在原序列中,r[i]=r[j],且r[i]在r[j]之前,而在排序后的序列中,r[i]仍在r[j]之前,则称这种排序算法是稳定的;否则称为不稳定的。

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

2.2 排序的运用

举个例子:
在京东上平板的统合排名:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
来看看高校的排名:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
可能每个人搜出来的不一样。

2.3 常见的排序算法

【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

3. 插入排序

3.1 基本思想

直接插入排序是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。
就像是在玩扑克牌时候,对刚拿的牌来进行一个插入。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

3.2 直接插入排序

当插入第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)
  3. 空间复杂度:O(1),它是一种稳定的排序算法
  4. 稳定性:稳定

3.2.1 直接插入排序实现

以升序为例子

3.2.1.1 分析

就是把没排好的数插入到已经排好的数中,实现有序。
实现排序,先实现单趟。
假设在一个已经排好序的区间[0,end],然后把end+1位置的值插入进去,那怎么插入呢?
从后往前,依次比较,如果比end+1大,那就往后挪,把位置空出来,再把值放进去。为了记录插入的数据,用一个临时变量tmp存储 end+1的值,避免被覆盖。

【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
假设前面的已经[0,end],也就是3,4,9已经排好。这时要插入6,先记录一下tmp=6,然后依次往前比较,如果比tmp大,那就往后挪。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
还有一种情况:
一直往走,往后挪数据,当end<0时结束。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
所以这里循环的条件就是while (end >= 0)
如果tmp < a[end],就实现a[end + 1] = a[end],然后end1--
循环结束就有两种情况:一种是tmp>=end,tmp就得放在end后面。另一种是:在while条件结束,出现end<0。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
单趟的已经实现,那怎么实现整体?
while循环外面再套一层循环。
第一个数据就是[0,0],再往下是[0,1],2位置的往前插入。那么它的结束位置就是n-1,不能是n,因为如果到n,那么tmp位置访问n+1,已经越界了。

3.2.1.2 代码实现
void InsertSort(int* a, int n)
{
	// [0, end] end+1
	for (int i = 0; i < n - 1; ++i)
	{
		int end =i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}

		a[end + 1] = tmp;
	}
}

来看看结果:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

3.3 希尔排序

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

  1. 希尔排序是对直接插入排序的优化。
  2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
  3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些书中给出的希尔排序的时间复杂度都不固定:
  4. 稳定性:不稳定

3.3.1 希尔排序实现

希尔排序分为两部分:第一部分是预排序,第二部分是直接插入排序。

3.3.1.1 分析

预排序的目的是让数组基本有序,这样直接插入就很快。
举个例子:gap=3
将间隔为3的分为一组,那么总的就分为了三组。红的一组,蓝的一组,绿的一组。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
那么它的预排序怎么实现呢?
就是将分的这三组,分别进行插入排序。
首先将9当成已经排好的数据,那么下一个不是8,而是间隔为3的6,把6往前插入,然后继续找下一个就是4,继续往前面插入。
最后就是这样;
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
剩下的两组也是一样的,最终排出来就是
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
这里只是接近有序。

就是把上面的直接插入排序的tmp换成end + gap位置的就行。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
假设先对红色这组经行排序,那就是:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
注意循环的条件如果是i<n,那么就会访问越界,注意看图上,发现结束的位置就是n-gap。
如果排实现的两组,那么就直接再套一层,循环gap=3次就排完了。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
这里套了三层排序,也只是预排序,j为0就是红色的一组,j为1就是蓝色那组,j为2就是绿色那一组。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
优化一下,实现多组并排,之间是一组一组往后排,现在是直接在gap组之间来回跳,第一次排红色,第二次排蓝色,第三次排绿色。
少一层循环。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
gap怎么选择:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

《数据结构(C语言版)》— 严蔚敏
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

《数据结构-用面相对象方法与C++描述》— 殷人昆
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
所以这里实现希尔排序,就是将gap不断变小,
gap > 1时是预排序,目的让他接近有序,而gap == 1是直接插入排序,目的是让他有序。
那么这里gap怎么选择呢?
如果gap = gap / 2,这里跳跃就比较小,所以选择gap = gap / 3 ,但为了保证最后一次为1,这里就得加1,也就是gap = gap / 3 + 1。
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法
来看看结果:
【数据结构】排序之插入排序,数据结构,数据结构,排序算法,算法

3.3.1.2 代码实现
void ShellSort(int* a, int n)
{
	int gap = n;
	// gap > 1时是预排序,目的让他接近有序
	// gap == 1是直接插入排序,目的是让他有序
	while (gap > 1)
	{
		//gap = gap / 2;
		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;
		}
	}
}

4. 附代码

4.1 sort.h

#pragma once
#include<stdio.h>
#include<assert.h>
#include<stdlib.h>
#include<stdbool.h>
#include<time.h>

void PrintArray(int* a, int n);
void InsertSort(int* a, int n);
void ShellSort(int* a, int n);

4.2 sort.c

#include"Sort.h"

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

// 时间复杂度:O(N^2) 逆序
// 最好的情况:O(N)  顺序有序
void InsertSort(int* a, int n)
{
	// [0, end] end+1
	for (int i = 0; i < n - 1; ++i)
	{
		int end =i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				--end;
			}
			else
			{
				break;
			}
		}

		a[end + 1] = tmp;
	}
}


// 平均O(N^1.3)
void ShellSort(int* a, int n)
{
	int gap = n;

	// gap > 1时是预排序,目的让他接近有序
	// gap == 1是直接插入排序,目的是让他有序
	while (gap > 1)
	{
		//gap = gap / 2;
		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;
		}
	}


	/*for (int j = 0; j < gap; ++j)
	{
		for (int i = j; 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;
		}
	}*/
}

4.3 test.c

#include"Sort.h"

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

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

在之后的博客中会继续分享与排序有关的内容,请多多关注。
有问题请指出,大家一起进步!
文章来源地址https://www.toymoban.com/news/detail-770888.html

到了这里,关于【数据结构】排序之插入排序的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 数据结构算法练习 插入排序 冒泡排序

    插入排序 代码如下  package main import \\\"fmt\\\" func main() {     a := []int{4, 5, 6, 1, 3, 2}         b := insert(a)     for i := 0; i len(b); i++ {         fmt.Println(b[i])     } } func insert(a []int) []int {     if len(a) = 1 {                   如果数组长度小于等于1 不用排序直接返回          retur

    2024年02月08日
    浏览(58)
  • 【数据结构】常见排序算法——常见排序介绍、插入排序、直接插入排序、希尔排序

      在计算机科学中,排序是将一组数据按照指定的顺序排列的过程。排序算法由于执行效率的不同可以分为多种不同的算法。   通常情况下,排序算法可以分为两类,即 内部排序和外部排序 。内部排序是指数据全部加载到内存中进行排序,适用于数据量较小的情况,而

    2024年02月08日
    浏览(63)
  • 数据结构算法--2 冒泡排序,选择排序,插入排序

    思想就是将相邻元素两两比较,当一个元素大于右侧相邻元素时,交换他们的位置,小于右侧元素时,位置不变,最终序列中的最大元素,像气泡一样,到了最右侧。 这时冒泡排序第一轮结束,数列最右侧元素9的位置可认为是一个有序区,有序区目前有一个元素. 第二轮排序

    2024年02月13日
    浏览(64)
  • 【数据结构与算法】排序算法(选择排序,冒泡排序,插入排序,希尔排序)

    基本概念这了就不浪费时间解释了,这四种都是很简单的排序方式,本专栏后续文章会出归并排序,计数排序,快速排序,堆排序,桶排序等排序算法,今天这篇文章中给出选择排序,冒泡排序,插入排序和希尔排序的实现; 如果发现文章中有错误,还请大家指出来,我会非

    2024年02月15日
    浏览(86)
  • 【数据结构与算法】:插入排序与希尔排序

    🔥 个人主页 : Quitecoder 🔥 专栏 : 数据结构与算法 欢迎大家来到初阶数据结构的最后一小节:排序 排序是一种将一组对象按照某种特定顺序重新排列的过程。在计算机科学中,排序是数据处理中非常基本且重要的操作,它可以帮助人们更有效地理解和分析数据。排序的顺序

    2024年03月18日
    浏览(39)
  • 【数据结构与算法】插入排序和希尔排序

      目录 一.插入排序  InsertSort 基本思想 动图演示  特性总结 二.希尔排序  ShellSort 基本思想 图例 特性总结 基本思想 把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。 当插入第i(i=1)个元素

    2023年04月18日
    浏览(89)
  • 【数据结构与算法】直接插入排序和希尔排序

    进入了初阶数据结构的一个新的主题——排序。所谓排序,就是一串记录, 按照其中的某几个或某些的大小(一定的规则) , 递增或递减排列起来的操作 。 排序的 稳定性 :在一定的规则下,两个值相等的元素,在排序算法处理前后的相对位置是否发生变化,如果相

    2024年04月13日
    浏览(44)
  • 【数据结构】排序算法(一)—>插入排序、希尔排序、选择排序、堆排序

    👀 樊梓慕: 个人主页   🎥 个人专栏: 《C语言》《数据结构》《蓝桥杯试题》《LeetCode刷题笔记》《实训项目》 🌝 每一个不曾起舞的日子,都是对生命的辜负 目录 前言 1.直接插入排序 2.希尔排序 3.直接选择排序 4.堆排序 本篇文章博主将介绍排序算法中的插入排序:直接

    2024年02月08日
    浏览(49)
  • 【数据结构与算法篇】手撕排序算法之插入排序与希尔排序

    ​👻内容专栏:《数据结构与算法篇》 🐨本文概括: 讲述排序的概念、直接插入排序、希尔排序、插入排序和希尔排序的区别。 🐼本文作者:花 碟 🐸发布时间:2023.6.13 排序 :所谓排序,就是使一串记录,按照其中的某个或某些的大小,递增或递减的排列起来的

    2024年02月09日
    浏览(51)
  • 读书笔记-《数据结构与算法》-摘要4[插入排序]

    核心:通过构建有序序列,对于未排序序列,在已排序序列中从后向前扫描(对于单向链表则只能从前往后遍历),找到相应位置并插入。实现上通常使用in-place排序(需用到O(1)的额外空间) 从第一个元素开始,该元素可认为已排序 取下一个元素,对已排序数组从后往前扫描 若从

    2024年02月04日
    浏览(37)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包