插入排序(直接插入排序与希尔排序)----数据结构-排序①

2024-06-04 00:20

本文主要是介绍插入排序(直接插入排序与希尔排序)----数据结构-排序①,希望对大家解决编程问题提供一定的参考价值,需要的开发者们随着小编来一起学习吧!

1、插入排序

1.1 插入排序的基本思想

        将待排序的元素按其数值的大小逐个插入到一个已经排好序的有序序列中,直到所有的元素插入完为止,就可以得到一个新的有序序列 。

实际上在我们的日常生活中,插入排序的应用是很广泛的,例如我们在玩扑克牌时,就利用了插入排序的思想,例如下图:

当我们手里已经具有 2、3、5、10 这样一个有序序列的扑克牌时,我们现在又出现一张 7 ,我们需要将其插入到我们已经有序的 2、3、5、10 序列中,我们先将需要插入的 7 与最后一张 10 进行大小比较,如果发现所插入的元素比 10 更小,就继续与前一个元素比较,直到发现所插入的元素大于该元素,就将其插入到该元素的后面即可。

1.2 直接插入排序 

有了上面对插入排序的理解,下面我们一起来学习一下直接插入排序。

排序思想:当我们插入第i(i>=1)个元素时,前面的array[0],array[1],…,array[i-1]已经排好序,此时用array[i]的数值与 先后与array[i-1],array[i-2],…的数值进行比较,找到合适位置就将array[i]插入,该位置后的所有元素都需要依次往后移。

下面是示意图:

代码实现:

void InsertSort(int* a, int n)
{for (int i = 0; i < n - 1; i++){int end = i;  // 这里我们认为 [ 0 , end] 是已经有序的int tmp = a[end + 1];   // 将 end+1 位置的元素与前面 [ 0 , end] 的元素进行比较// 找到合适的位置就插入while (end >= 0){if (tmp < a[end]) // 如果前面的数据比 tmp 大就将该数据往后挪{                 // 并且比较 --end ,使tmp继续与前一个数据进行比较a[end + 1] = a[end];--end;}// tmp >= a[end]else   // 遇到前面的数据比 tmp 小或相等就跳出循环break;}// 此时 end+1的位置是空出来的,即 tmp 所插入的位置a[end + 1] = tmp;}
}

直接插入排序的特性总结:

1. 元素集合越接近有序,直接插入排序算法的时间效率越高

2. 时间复杂度:O(N^2)

3. 空间复杂度:O(1),它是一种稳定的排序算法

4. 稳定性:稳定 

 1.3 希尔排序( 缩小增量排序 )

        希尔排序法又称缩小增量法。希尔排序法的基本思想是:先选定一个整数 gap(一组当中相邻元素的距离) ,把待排序文件中所有数分成个 gap (N是数据总个数)组,所有距离为 gap 的数分在同一组内,并分别对每一组内的数据进行一次插入排序。然后让 gap 不断的缩小,并重复上述分组和排序的工作。当到达 gap = 1 时,相当于进行了一次直接插入排序,这一次排序结束后,所有数在同一组内被排好序。

下面是希尔排序动图演示:

 gap的取法:

gap的取法有很多种,但主流的两种取法是 :①gap = gap/2;②gap = gap/3 +1。

下面我们以gap = gap/3 + 1 这种取法为例。

代码实现:

void ShellSort(int* a, int n)
{assert(a);int gap = n;//不能写成大于0,因为gap的值始终>=1while (gap > 1){//只有gap最后为1,才能保证最后有序//所以这里要加1gap = gap / 3 + 1;//这里只是把插入排序的1换成gap即可//但是这里不是排序完一个分组,再去//排序另一个分组,而是整体只过一遍//这样每次对于每组数据只排一部分//整个循环结束之后,所有组的数据排序完成for (int i = 0; i < n - gap; ++i){int end = i;int tmp = a[end + gap];while (end >= 0 && a[end] > tmp){a[end + gap] = a[end];end -= gap;}a[end + gap] = tmp;}}
}

希尔排序的特性总结:

1. 希尔排序是对直接插入排序的优化。

2. 当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。

3. 希尔排序的时间复杂度不好计算,因为gap的取值方法很多,导致很难去计算,因此在好些树中给出的希尔排序的时间复杂度都不固定,一般认为希尔排序的时间复杂度是O(^{_{N^{1.3}}})

这篇关于插入排序(直接插入排序与希尔排序)----数据结构-排序①的文章就介绍到这儿,希望我们推荐的文章对编程师们有所帮助!



http://www.chinasem.cn/article/1028533

相关文章

【数据结构】——原来排序算法搞懂这些就行,轻松拿捏

前言:快速排序的实现最重要的是找基准值,下面让我们来了解如何实现找基准值 基准值的注释:在快排的过程中,每一次我们要取一个元素作为枢纽值,以这个数字来将序列划分为两部分。 在此我们采用三数取中法,也就是取左端、中间、右端三个数,然后进行排序,将中间数作为枢纽值。 快速排序实现主框架: //快速排序 void QuickSort(int* arr, int left, int rig

usaco 1.3 Mixing Milk (结构体排序 qsort) and hdu 2020(sort)

到了这题学会了结构体排序 于是回去修改了 1.2 milking cows 的算法~ 结构体排序核心: 1.结构体定义 struct Milk{int price;int milks;}milk[5000]; 2.自定义的比较函数,若返回值为正,qsort 函数判定a>b ;为负,a<b;为0,a==b; int milkcmp(const void *va,c

hdu 1285(拓扑排序)

题意: 给各个队间的胜负关系,让排名次,名词相同按从小到大排。 解析: 拓扑排序是应用于有向无回路图(Direct Acyclic Graph,简称DAG)上的一种排序方式,对一个有向无回路图进行拓扑排序后,所有的顶点形成一个序列,对所有边(u,v),满足u 在v 的前面。该序列说明了顶点表示的事件或状态发生的整体顺序。比较经典的是在工程活动上,某些工程完成后,另一些工程才能继续,此时

6.1.数据结构-c/c++堆详解下篇(堆排序,TopK问题)

上篇:6.1.数据结构-c/c++模拟实现堆上篇(向下,上调整算法,建堆,增删数据)-CSDN博客 本章重点 1.使用堆来完成堆排序 2.使用堆解决TopK问题 目录 一.堆排序 1.1 思路 1.2 代码 1.3 简单测试 二.TopK问题 2.1 思路(求最小): 2.2 C语言代码(手写堆) 2.3 C++代码(使用优先级队列 priority_queue)

《数据结构(C语言版)第二版》第八章-排序(8.3-交换排序、8.4-选择排序)

8.3 交换排序 8.3.1 冒泡排序 【算法特点】 (1) 稳定排序。 (2) 可用于链式存储结构。 (3) 移动记录次数较多,算法平均时间性能比直接插入排序差。当初始记录无序,n较大时, 此算法不宜采用。 #include <stdio.h>#include <stdlib.h>#define MAXSIZE 26typedef int KeyType;typedef char In

【软考】希尔排序算法分析

目录 1. c代码2. 运行截图3. 运行解析 1. c代码 #include <stdio.h>#include <stdlib.h> void shellSort(int data[], int n){// 划分的数组,例如8个数则为[4, 2, 1]int *delta;int k;// i控制delta的轮次int i;// 临时变量,换值int temp;in

学习记录:js算法(二十八):删除排序链表中的重复元素、删除排序链表中的重复元素II

文章目录 删除排序链表中的重复元素我的思路解法一:循环解法二:递归 网上思路 删除排序链表中的重复元素 II我的思路网上思路 总结 删除排序链表中的重复元素 给定一个已排序的链表的头 head , 删除所有重复的元素,使每个元素只出现一次 。返回 已排序的链表 。 图一 图二 示例 1:(图一)输入:head = [1,1,2]输出:[1,2]示例 2:(图

【408数据结构】散列 (哈希)知识点集合复习考点题目

苏泽  “弃工从研”的路上很孤独,于是我记下了些许笔记相伴,希望能够帮助到大家    知识点 1. 散列查找 散列查找是一种高效的查找方法,它通过散列函数将关键字映射到数组的一个位置,从而实现快速查找。这种方法的时间复杂度平均为(

鸡尾酒排序算法

目录 引言 一、概念 二、算法思想 三、图例解释 1.采用冒泡排序:   2.采用鸡尾酒排序:  3.对比总结 四、算法实现  1.代码实现  2.运行结果 3.代码解释   五、总结 引言 鸡尾酒排序(Cocktail Sort),也被称为双向冒泡排序,是一种改进的冒泡排序算法。它在冒泡排序的基础上进行了优化,通过双向遍历来减少排序时间。今天我们将学习如何在C

快速排序(java代码实现)

简介: 1.采用“分治”的思想,对于一组数据,选择一个基准元素,这里选择中间元素mid 2.通过第一轮扫描,比mid小的元素都在mid左边,比mid大的元素都在mid右边 3.然后使用递归排序这两部分,直到序列中所有数据均有序为止。 public class csdnTest {public static void main(String[] args){int[] arr = {3,