• DSA之排序(2):插入排序


    1 插入排序

    1.1 基本思想

    把待排序的,插入到已经排好序的合适的位置。
    在这里插入图片描述

    边插入边排序,保证子序列都是排好序的。

    1.2 基本操作

    在这里插入图片描述
    在这里插入图片描述

    1.3 插入位置

    在这里插入图片描述
    Q:如何找到插入位置?
    A:下方的插入排序方法将会介绍。

    2 插入排序的种类

    在这里插入图片描述

    2.1 直接插入排序

    采用顺序查找法查找插入位置。
    在这里插入图片描述
    循环跳出条件为:j >= 0 && x < a[j]
    从后往前找,但有个问题,每次循环都要判断两个,时间太久,之前在顺序查找法的时候,有个带哨兵的,现在可以用上。直接把待插入元素第i个位置上的元素放到下标为0的位置(哨兵位置)上面。
    在这里插入图片描述

    2.1.1 直接插入排序算法

    void InsertSort(SqList &L)
    {
    	int i, j;
    	for (i = 2; i <= L.length(); ++i)
    	{
    		if (L.r[i].key < L.r[i-1].key)//若"<",需要将L.r[i]插入到有序子表
    		{
    			L.r[0] = L.r[i];//复制2为哨兵,减少循环的比较条件
    	for (j = i-1; L.r[0].key < L.r[j].key; --j)
    			{
    				L.r[j+1] = L.r[j];//记录后移
    			}
    			L.r[j+1] = L.r[0];//插入到正确的位置
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    2.1.2 性能分析

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.1.3 结论

    在这里插入图片描述

    2.2 折半插入排序

    直接插入法是在查找位置的时候,从后往前依次进行比较的,这种一个一个进行比较的方法叫做顺序查找法。折半查找法定义一个low端一个high端,找到mid中间位置,与哨兵位置比较,mid比哨兵小,就在右半区域进行查找;反之亦然。找到后依然是要将位置向后移动,然后将哨兵位置的元素放到合适的位置。

    2.2.1 折半插入排序算法

    void BInsertSort(SqList &L)
    {
    	for (i = 2; i <= L.length(); ++i)//依次插入第2~第n个位置
    	{
    		L.r[0] = L.r[i];//当前插入元素存到哨兵位置
    		low = 1;
    		high = i-1;//采用二分查找法查找插入位置
    		while(low <= high)
    		{
    			mid = (low + high) / 2;
    			if (L.r[0].key < L.r[mid].key)
    			{
    				high = mid - 1;
    			}
    			else 
    			{
    				low = mid + 1;
    			}
    		}//循环结束,high+1则为插入位置
    		for (j = i-1; j >= high+1; --j)
    		{
    			L.r[j+1] = L.r[j];//移动元素
    		}
    		L.r[high+1] = L.r[0];//插入到正确的位置
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16
    • 17
    • 18
    • 19
    • 20
    • 21
    • 22
    • 23
    • 24
    • 25
    • 26

    2.2.2 性能分析

    在这里插入图片描述
    在这里插入图片描述

    折半只是减少了比较的次数,移动的次数没有减少。

    2.3 希尔排序

    在这里插入图片描述
    希尔排序算法的出发点,就是怎么能够在进行插入排序的时候基本有序,怎么能比较一次就移动一大步,相当于是继承了上方几种排序的优点。

    基本思想:
    先将整个待排记录序列分割成若干子序列(元素个数就少了,交换的时候可以移动一大步),分别进行直接插入排序,待整个序列中的记录“基本有序”时,再对全体记录进行一次直接插入排序。

    希尔排序算法,特点:

    • 缩小增量
    • 多遍插入排序

    在这里插入图片描述

    思路:
    在这里插入图片描述
    最后一次是1间隔的插入排序。

    特点:

    在这里插入图片描述

    2.3.1 希尔排序算法

    //主程序
    void ShellSort(SqList &L, int dlta[], int t)
    {
    //按增量序列dlta[0...t-1]对顺序表L作希尔排序
    	for (k=0; k<t; ++k)
    	{
    		ShellInsert(L, dlta[k]);//一趟增量为dlta[k]得到插入排序,总共是循环的t趟
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    //其中一趟的排序操作
    void ShellInsert(SqList &L, int dk)
    {
    	for (i=dk+1; i<=L.length(); ++i)
    	{
    		if (r[i].key < r[i-dk].key)
    		{
    			r[0] = r[i];
    for (j=i-dk; j>0 && (r[0].key<r[j].key);j=j-dk)
    			{
    				r[j+dk]=r[j];
    			}
    			r[j+dk] = r[0];
    		}
    	}
    }
    
    • 1
    • 2
    • 3
    • 4
    • 5
    • 6
    • 7
    • 8
    • 9
    • 10
    • 11
    • 12
    • 13
    • 14
    • 15
    • 16

    本质上还是插入排序,但是按照间隔来的。

    2.3.2 性能分析

    在这里插入图片描述
    在这里插入图片描述
    非稳定性算法
    在这里插入图片描述

    2.3.3 结论

    在这里插入图片描述

  • 相关阅读:
    开发者举报:“除了每年收我的钱,苹果似乎什么都不想做”
    『现学现忘』Docker相关概念 — 3、IaaS、SaaS、PaaS服务模式补充
    ElementUI浅尝辄止30:PageHeader 页头
    如何全面去理解通达信接口API?
    MySQL MHA高可用配置及故障切换
    Llama-2 推理和微调的硬件要求总结:RTX 3080 就可以微调最小模型
    针对结构映射的SVM算法:核心思路解读
    vs2022不能加载winform界面
    DPDK之什么是imissed、ierrors、rx_nombuf
    IPv6进阶:IPv6 过渡技术之 6to4 自动隧道
  • 原文地址:https://blog.csdn.net/weixin_44673253/article/details/126243477