当前位置: 首页 > article >正文

【算法】直接插入排序、折半插入排序、希尔排序

1 直接插入排序

时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定

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

1.1直接插入排序思想

把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。

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

在这里插入图片描述

1.2直接插入排序代码实现

在这里插入图片描述

void InsertSort(int* a, int n)//直接插入排序:	时间复杂度:O(n*n)	空间复杂度:O(1)
{
	assert(a);

	for (int i = 1; i < n; i++)//总共插入n-1次
	{
		int temp = a[i];//将最后一个数保存下来
		int point = i-1;//从倒数第二个数依次往前遍历

		while (point >= 0)//单趟把末尾的数插入到正确的位置
		{
			if (temp < a[point])//把大的数后移(为了保有稳定性,相等的数不后移)
			{
				a[point + 1] = a[point];
				point--;
			}
			else//因为前面已经排好序了,小于当前的就肯定小于前面的,直接break
			{
				break;
			}
		}
		a[point + 1] = temp;//把数插入到对应的位置
	}
}

2 折半插入排序

时间复杂度:O(N^2)
空间复杂度:O(1)
稳定性:稳定

此算法改变了比较元素的次数,比较的时间复杂度约为O(nlogn),但并未改变元素移动的次数,所以总体来看折半插入排序的时间复杂度仍然是O(n*n)

2.1折半插入排序思想

折半插入排序是直接插入排序的优化,在进行第n个数的插入时,对前面0~n-1个数进行二分查找,找到比第n个数小的数的下标,随后进行后移操作。

2.2折半插入排序代码实现

void InsertSort_Binary(int* a, int n)//折半插入排序:	时间复杂度:O(n*n)	空间复杂度:O(1)
{
	assert(a);

	for (int i = 1; i < n; i++)//总共插入n-1次
	{
		int temp = a[i];//将最后一个数保存下来
		int left = 0;
		int right = i - 1;
		int mid;

		while (left<=right)//单次找到小于temp的值的位置
		{
			mid = (left + right) / 2;
			if (temp >= a[mid])
			{
				left = mid + 1;
			}
			else
			{
				right = mid - 1;
			}
		}

		for (int j = i - 1; j >= left; j--)//把此位置及其之后全部后移1位
		{
			a[j + 1] = a[j];
		}
		a[left] = temp;

	}
}

3 希尔排序

时间复杂度:O(n^1.3)——O(n*n)
空间复杂度:O(1)
稳定性:不稳定

《数据结构(C语言版)》— 严蔚敏
在这里插入图片描述

《数据结构-用面相对象方法与C++描述》— 殷人昆在这里插入图片描述

3.1希尔排序思想

由前面我们知道,元素集合越接近有序,直接插入排序算法的时间效率越高。所以我们先对数组进行预排序。

先选定一个整数,把待排序文件中所有记录分成个组,所有距离为的记录分在同一组内,并对每一组内的记录进行排序。然后重复上述分组和排序的工作。当到达=1时,所有记录在统一组内排好序。
在这里插入图片描述

3.2希尔排序代码实现

void ShellSort(int* a, int n)//希尔排序:	时间复杂度:O(n^1.3)-O(n^2)	
{
	int gap = n; 

	while (gap > 1)//gap>1时相当于预排序
	{
		gap = gap / 3 + 1;//+1保证了最后一次gap一定是1 

		for (int i = gap; i < n ; i++)//每一轮走(n-gap)次 
		{
			int temp = a[i];//将最后一个数保存下来(每组的最后一个)
			int point = i - gap;//从倒数第二个数依次往前遍历(每组的倒数第二个)
			while (point >= 0)//单趟把末尾的数插入到正确的位置
			{
				if (temp < a[point])
				{
					a[point+gap] = a[point];
					point -= gap;
				}
				else
				{
					break;
				}
			}
			a[point+gap] = temp;
		}
	}
}

http://www.kler.cn/a/557648.html

相关文章:

  • Dockerfile中volume功能作用
  • ok113i平台——更改根目录分区大小
  • 【深度学习】Pytorch的深入理解和研究
  • 跟着李沐老师学习深度学习(十二)
  • Cython学习笔记1:利用Cython加速Python运行速度
  • 算法日记25:01背包(DFS->记忆化搜索->倒叙DP->顺序DP->空间优化)
  • HDFS入门与应用开发
  • 蓝桥杯——按键
  • 从零搭建微服务项目Pro(第1-1章——Quartz实现定时任务模块)
  • 实现 INFINI Console 与 GitHub 的单点登录集成:一站式身份验证解决方案
  • 国产编辑器EverEdit - 洞察秋毫!内置文件比较功能!
  • 正确清理C盘空间
  • 【AI】常见的AI工具地址和学习资料链接
  • INDEMIND:AI视觉赋能服务机器人,“零”碰撞避障技术实现全天候安全
  • picgo-plugin-huawei插件发布
  • github配置sshkey
  • Apipost 与 Postman 工具实践指南:WebSocket调试与动态参数测试
  • springboot单机支持1w并发,需要做哪些优化
  • Mac m1 连接公司内网
  • 期权帮|股指期货中的套期保值如何操作?