排序(插入,希尔,堆排)

常见的排序算法:

插入排序:

直接插入排序:是一种简单的插入排序法,其基本思想是:把待排序的记录按其关键码值的大小逐个插入到一个已经排好序的有序序列中,直到所有的记录插入完为止,得到一个新的有序序列 。保证插入之前的数组是有序的,插入后也保证是有序的。时间复杂度:原数组如果和需要排的顺序逆序的时候是最坏的情况,O(N^2),和冒泡排序时间复杂度相同。最好的情况是O(N),顺序有序。

c 复制代码
// 直接插入插入排序
void InsertSort(int* a, int n)
{
	//多趟排序
	for(int i = 0; i < n-1; ++i) // 当n = n-2时,插入的就是第n-1的位置的值,就完成了n个数的插入。
	{
		// 单趟排序 把tmp插入数组[0,end]的有序区间
		int end = i; // 从后往前判断,end 就是当前判断的最后一个值
		int tmp = a[end + 1]; // end外面要插入的数据
		while(end >= 0) // 从后往前,end--
		{
			if(tmp < a[end])
			{
				a[end + 1] = a[end]; //让end位置的值放在end+1的位置
				end--; 
			}
			else
				break; // 说明tmp >= a[end-1]
		}
		a[end + 1] = tmp; // 需要在end-1的后面 也就是end+1的位置存放tmp
	}
} 

希尔排序:再插入排序的基础上,让数组首先接近于有序。也就是1.预排序 ->让数组接近有序,2.直接插入排序。

预排序 ->先分组,对分组的数据进行插入排序。间隔为gap的分成一组,对一组进行插入排序。

蓝色的整体为一组,红色的整体为一组,绿色的整体为一组。每次比较的时候只比较各自颜色指向的数字,以蓝色为例,也就是9,5,8,5相比较后进行排序。

gap越大,说明大的数和小的数可以更快的挪到对应的位置,但gap越大越不接近有序。gap越小则相反。

如果gap==1,则就是直接插入排序。排序的规则就是gap = 5, gap = 3, gap = 1来三次就完成希尔排序。

希尔排序的时间复杂度不好计算,需要进行推导,推导出来平均时间复杂度: O(N^1.3和 N^2)

c 复制代码
 // 希尔排序
void ShellSort(int* a, int n)
{
	int gap = n;
	// gap>1是预排序让它接近有序,gap == 1,就是直接插入排序O(N)。
	while(gap > 1)
	{
		gap = (gap / 3 + 1); //这样可以保证gap最后一次是1。
		// i<n-gap 则对应上图的话就到蓝色8这个位置,i一直加到这个位置可以把蓝色红色和绿色全部处理完。
		// 也就是 先蓝色,再红色,再绿色,再蓝色,再红色,再绿色,再蓝色(8这个位置)就完了。因为后面红色绿色只有一个数。
		for(int i = 0; i < n-gap; ++i) 
		{
			int end = i;
			int tmp = a[end + gap]; //要插入的值
			while(end >= 0) // 间隔为gap的排序,类似于直接插入排序(间隔为1)
			{
				if(tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
					break;
			}
			a[end + gap] = tmp;
		}
	}
}

直接选择排序:在数组中直接选择最大的,次大的放到相应位置直接排。

c 复制代码
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
// 选择排序
void SelectSort(int* a, int n)
{
	// 将最小的放在最左边,最大的放在最右边,让左右位置往中间夹
	int left = 0;
	int right = n-1;
	while(left < right)
	{
		int minIndex = left, maxIndex = left;
		for(int i=left; i<right; ++i)
		{
			if(a[i] < a[minIndex]) // 选出最小的
				minIndex = i;
			if(a[i] > a[maxIndex]) //选出最大的
				maxIndex = i;
		}
		Swap(&a[left], &a[minIndex]); 
		//如果最大值在left位置,上面交换后max就被换走了 换到minIndex的位置去了 修正位置。
		if(left == maxIndex) 
		{
			maxIndex = minIndex;
		}
		Swap(&a[right], &a[maxIndex]);
		++left;
		--right;
	}
}

堆排序:先得有个堆然后再选择出放到特定位置的选择排序方法。
堆排序的详细介绍

c 复制代码
void Swap(int* p1, int* p2)
{
	int tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
 // 堆排序 
 //自顶向下的调整,但是parent的传参是自下而上的传,先保证最下面的parent及其子节点属于大堆,再一层一层的向上传parent。
void AdjustDwon(int* a, int n, int parent)
{
	int child = parent*2 + 1;
	while(child < n)
	{
		// 建大堆 选出左右孩子大的
		if(child + 1 < n && a[child + 1] > a[child])
		{
			child++;
		}
		if(a[parent] < a[child])
		{
			Swap(&a[parent], &a[child]);
			parent = child;
			child = parent*2 + 1;
		}
		else
			break;
	}
}
void HeapSort(int* a, int n)
{
	// 建堆 parent的传参是自下而上的传,先保证最下面的parent及其子节点属于大堆,再一层一层的向上传parent。
	for(int i = (n-1-1)/2; i >=0; --i)
	{
		AdjustDwon(a, n, i);
	}
	int end = n-1;
	while(end > 0)
	{
		Swap(&a[0], &a[end]);
		// 再选出次大的 因为之前已经建堆完成了,因此只有换上去到最上面的那个数不满足大堆的排序,把它排好就行
		AdjustDwon(a, end, 0)
		end--; //每次最后一个位置就是被调换过的最大的、次大的...的数
	}
}
相关推荐
shiji-lu8 分钟前
针对考研的C语言学习(定制化快速掌握重点1)
c语言·学习·考研
Eric.Lee202127 分钟前
数据集-目标检测系列-海洋鱼类检测数据集 fish>> DataBall
人工智能·算法·目标检测·数据集·物体检测·鱼类检测
山语山28 分钟前
目标检测DOTA数据集
javascript·人工智能·算法·目标检测·计算机视觉·github
DR-ZF-1 小时前
20240924 行列式为1的矩阵不一定是正交矩阵
线性代数·算法·矩阵
听风客11 小时前
P2415 集合求和
c++·算法
LDG_AGI1 小时前
【人工智能】Transformers之Pipeline(十九):文生文(text2text-generation)
人工智能·python·算法·机器学习·视觉检测·aigc·机器翻译
青椒大仙KI111 小时前
24/9/24 算法笔记 超参数优化算法
人工智能·笔记·算法
希望有朝一日能如愿以偿1 小时前
字符串哈希
数据结构·算法·哈希算法
m0_699990952 小时前
My_String完善
开发语言·c++·算法
极客小张2 小时前
基于STM32与OpenCV的物料搬运机械臂设计流程
c语言·arm开发·stm32·单片机·opencv·物联网·算法