排序之归并排序

news2024/11/27 4:28:42

文章目录

  • 前言
  • 一、归并排序
    • 1、归并排序基本思想
    • 2、归并排序代码实现
    • 3、归并排序效率分析
  • 二、归并排序非递归实现(循环实现)
    • 1、归并排序非递归实现(循环实现)基本思想
    • 2、归并排序非递归实现(循环实现)代码
  • 三、计数排序
    • 1、计数排序基本思想
    • 2、计数排序代码实现
    • 3、计数排序效率分析


前言

一、归并排序

1、归并排序基本思想

归并排序(MERGE-SORT)是建立在归并操作上的一种有效的排序算法,该算法是采用分治法(Divide and Conquer)的一个非常典型的应用。将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
所谓归并,就是将两组有序的数据合成为一组有序的数据,例如有如下两个有序数组,将两个有序数组归并为一个有序数组,这就是一次归并操作。
在这里插入图片描述
归并排序类似于二叉树的后序遍历,即先将左右的区间都排为有序后,然后才开始进行归并操作,因为归并必须要满足两个数组是有序的。
例如有如下数组。需要先将该数组每次都分割为两个区间,直到最后每个区间都只有一个值,此时比较两个值大小,然后将该两个值归并到一个数组中,此时就得到一个有两个元素的有序数组,然后再与另一个有两个元素的有序数组进行归并,然后就得到了一个有四个元素的有序数组,然后再与另一个有四个元素的有序数组进行归并,就得到了一个有八个元素的有序数组。就这样依次递归归并,直到最后目标数组为有序数组。综上可以知道归并排序也用到了分治思想。
在这里插入图片描述

2、归并排序代码实现

每次将两个有序序列归并为一个有序序列后,此时只是在tmp辅助数组中有序,而在arr中还是两个有序序列并没有归并为一个有序序列,所以最后要做的就是将tmp数组中这一块归并后的有序序列拷贝到arr数组中。

void _MergeSort(int* arr, int begin, int end, int* tmp)
{
	if (begin >= end)
	{
		return;
	}
	//分治递归,让子区间先有序
	int mid = (begin + end) / 2;
	_MergeSort(arr, begin, mid, tmp);
	_MergeSort(arr, mid + 1, end, tmp);
	
	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int end2 = end;
	int i = begin1;
	//在arr[begin1,end1]和arr[begin2,end2]两个区间中开始归并
	while ((begin1 <= end1) && (begin2 <= end2))
	{
		//如果arr[begin1]的值小,就让arr[begin1]的值先进入tmp数组
		if (arr[begin1] < arr[begin2])
		{
			tmp[i++] = arr[begin1++];
		}
		//如果arr[begin2]的值小于等于arr[begin1],就让arr[begin2]的值进入tmp数组
		else
		{
			tmp[i++] = arr[begin2++];
		}
	}
	//如果数组1中的数据还没有归并到tmp中完,就直接将剩下的都放到tmp中
	while (begin1 <= end1)
	{
		tmp[i++] = arr[begin1++];
	}
	//如果数组2中的数据还没有归并到tmp中完,就直接将剩下的都放到tmp中
	while (begin2 <= end2)
	{
		tmp[i++] = arr[begin2++];
	}
	//把归并数据拷贝到原数据
	memcpy(arr + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
void MergeSort(int* arr, int n)
{
	//归并排序需要先申请一个辅助数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("MergeSort malloc fail");
		exit(-1);
	}
	_MergeSort(arr, 0, n - 1, tmp);
}

下面的图为归并排序中递归到最后begin和end相等时,就不再进行递归,然后此时返回上一个函数,执行后面的归并操作。归并操作就是同时遍历两个有序序列,然后比较元素大小,将小的元素放入到tmp数组中,当两个有序序列中有一个遍历完时,就将另一个剩下的元素都直接加到tmp数组中,此时tmp数组中[begin1,end2]之间就是归并为一个的有序序列了。
在这里插入图片描述

3、归并排序效率分析

归并排序的时间复杂度为O(N * log2N),因为向下递归的复杂度为O(log2N),然后遍历一遍数组的复杂度为O(N),所以总的时间复杂度为O(N * log2N)
归并排序的空间复杂度为O(N),因为需要创建一个tmp辅助数组用来存归并后的序列。

二、归并排序非递归实现(循环实现)

1、归并排序非递归实现(循环实现)基本思想

在使用递归进行归并排序时,我们分析了函数递归到最后时,两个需要归并的数组中每个数组里面只有一个元素,所以直接比较两个元素大小,然后再添加到tmp数组中,然后再返回上一层函数中;此时该层函数中两个需要归并的数组中每个数组里面有两个元素,并且这两个元素已经为有序,所以这次归并就是同时开始遍历这两个数组,然后选出最小的元素加入tmp数组中,然后再遍历下一个元素。依次类推上去,直到回到第一次调用函数,此时数组arr中左边的数组有序,右边的数组也有序,此时将左右两个数组进行归并,然后放入到tmp中,等左右两个数组的元素都进入tmp中时,此时tmp数组为有序数组,而arr数组中还是左右两组数据有序,此时将tmp中的内容拷贝到arr,arr也变为有序数组了。
利用循环实现归并排序时,我们也可以先将数组中每一个数为一组,然后让两个数归并为一个含有两个元素的有序数组,然后再让两个含有两个元素的有序数组归并为一个含有四个元素的有序数组,然后再让两个含有四个元素的有序数组归并为一个含有八个元素的有序数组,就这样一直循环下去,直到总数组有序。
例如如下数组的归并过程。
在这里插入图片描述

2、归并排序非递归实现(循环实现)代码

当gap为1时,代表两个需要归并的数组中每个数组只有一个元素。
在这里插入图片描述
当gap为2时,代表两个需要归并的数组中每个数组有两个元素。
在这里插入图片描述
当gap为4时,代表两个需要归并的数组中每个数组有四个元素。
在这里插入图片描述

void MergeSortNonR(int* arr, int n)
{
	//归并排序需要先申请一个辅助数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("MergeSort malloc fail");
		exit(-1);
	}
	int i = 0;
	//gap为每次需要归并的两个数组中有几个元素
	int gap = 1;
	//当gap为n/2时,此时为最后一次归并
	while (gap < n)
	{
		//每次都从数组起始位置开始,然后选2*gap个元素,前gap个为一个数组,后gap个为一个数组,然后让这两个数组进行归并
		for (i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;
			int j = begin1;
			//归并操作
			while ((begin1 <= end1) && (begin2 <= end2))
			{
				if (arr[begin1] < arr[begin2])
				{
					tmp[j++] = arr[begin1++];
				}
				else
				{
					tmp[j++] = arr[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = arr[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = arr[begin2++];
			}
		}
		//此时arr中从起始位置开始,让每gap个元素为一个数组,则这些数组都是有序的,
		//然后将这些数组每两组归并为一个更大的有序数组
		gap = gap * 2;
	}
	
	//此时tmp辅助数组的数据经过一步步归并成为了有序的,而arr数组中的数据还是无序的,所以要将tmp中的内容拷贝到arr中。
	memcpy(arr, tmp, sizeof(int) * n);
	//释放辅助数组的空间
	free(tmp);
}

上面的代码当排序2的幂次方个数据时没有问题,但是当排序数据的长度不是2的幂次方时,就会出现数组越界情况。例如当数组中有10个元素时,此时gap=1,还没有出现越界情况。
在这里插入图片描述
但是当gap为2时,此时当i=8时,begin1=8, end1=9, 但是begin2=10, end2=11,此时arr[begin2]和arr[end2]已经越界访问数组arr了。
在这里插入图片描述
当gap为4时,此时当i=8时,begin1=8, 但是en1=11, begin2=12, end2=15,此时
arr[end1]和arr[begin2]和arr[end2]都已经越界访问数组arr了。
在这里插入图片描述
当gap为8时,此时当i=0时,begin1=0, end1=7, begin2=8, 但是end2=15,此时
arr[end2]就已经越界访问数组arr了。
在这里插入图片描述
我们通过上面的分析知道了在什么情况时会造成越界访问,但是我们应该怎么修改代码呢?我们可以判断当begin1、end1、begin2、end2造成越界访问时,此时我们将该区间设置为不存在的区间,即进行边界修正,则在循环时该区间就不会进入循环,就不会造成越界访问了。
情况1:例如当求出begin2=10时,此时判断begin2>=n,则将begin2=10,end2=9,此时就不会进行下面的while ((begin1<=end1) && (begin2<=end2))循环,因为begin2>end2。
在这里插入图片描述
即此时会直接进入while (begin1 <= end1)循环中,然后将区间[begin1,end1]内的数据都放到tmp的[begin1,end1]区间内。
在这里插入图片描述
情况2:例如当end1=11,此时end1越界,则就需要设置end1=n-1,即将[begin1,n-1]区间内的元素归并即可。并且要将begin2=n,end2=n-1,即将[begin2,end2]设置为不存在区间,这样就不会进入while ((begin1<=end1) && (begin2<=end2))循环,因为begin2>end2。
在这里插入图片描述
此时会直接进入while (begin1 <= end1)循环中,然后将区间[begin1,n-1]内的元素都归并到tmp数组中即可。
在这里插入图片描述
情况3:例如当end2=15时,此时只有end2越界了,所以直接将end2=n-1,此时还会进入while ((begin1<=end1) && (begin2<=end2))循环中,因begin2<=end2。
在这里插入图片描述
此时两个需要归并的有序数组中,第二个数组只有两个元素,但是也可以正常进行归并操作。
在这里插入图片描述

void MergeSortNonR(int* arr, int n)
{
	//归并排序需要先申请一个辅助数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("MergeSort malloc fail");
		exit(-1);
	}
	int i = 0;
	//gap为每次需要归并的两个数组中有几个元素
	int gap = 1;
	//当gap为n/2时,此时为最后一次归并
	while (gap < n)
	{
		//每次都从数组起始位置开始,然后选2*gap个元素,前gap个为一个数组,后gap个为一个数组,然后让这两个数组进行归并
		for (i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;
			//printf("%d %d %d %d\n", begin1, end1, begin2, end2);
			//先判断求出来的区间是否有越界区间
			//如果end1越界,则此时归并时只归并[begin1,n-1]区间
			if (end1 >= n)
			{
				//此时end1已经越界,则将end1直接为n-1,
				end1 = n - 1;
				//此时end1=i+gap-1都越界了,所以begin2=i+gap和end2=i+2*gap-1都会越界
				//所以此时将begin2=n,end2=n-1,此时begin2>=en2,就不会进入循环
				begin2 = n;
				end2 = n - 1;
			}
			//此时[begin2,end2]区间越界,则归并时就不用归并该区间
			if (begin2 >= n)
			{
				begin2 = n;
				end2 = n - 1;
			}
			//此时end2越界,则归并时只需归并[begin2,n-1]区间即可
			if (end2 >= n)
			{
				end2 = n - 1;
			}

			int j = begin1;
			//归并操作
			while ((begin1 <= end1) && (begin2 <= end2))
			{
				if (arr[begin1] < arr[begin2])
				{
					tmp[j++] = arr[begin1++];
				}
				else
				{
					tmp[j++] = arr[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = arr[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = arr[begin2++];
			}
		}
		//此时tmp辅助数组的数据为有序的,而arr数组中的数据还是无序的,所以要将tmp中的内容拷贝到arr中。
		memcpy(arr, tmp, sizeof(int) * n);
		//此时arr中从起始位置开始,让每gap个元素为一个数组,则这些数组都是有序的,
		//然后将这些数组每两组归并为一个更大的有序数组
		gap = gap * 2;
	}
	
	//释放辅助数组的空间
	free(tmp);
}

上面代码为当遇到越界时,我们使用修正边界来使越界的区间变为不存在区间,那样归并时就不会将这些不存在区间的数据进行归并。下面的代码为当我们遇到越界时,如果是end1和begin2越界,直接不再进行下面的归并,直接跳出这次循环即可,而如果是end2越界,就将end2调整为n-1,此时就要进入
while ((begin1<=end1) && (begin2<=end2))循环中进行[begin1,end1]和[begin2,n-2]区间内数据的归并操作。

//将越界的元素直接不进行归并操作
void MergeSortNonR(int* arr, int n)
{
	//归并排序需要先申请一个辅助数组
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("MergeSort malloc fail");
		exit(-1);
	}
	int i = 0;
	//gap为每次需要归并的两个数组中有几个元素
	int gap = 1;
	//当gap为n/2时,此时为最后一次归并
	while (gap < n)
	{
		//每次都从数组起始位置开始,然后选2*gap个元素,前gap个为一个数组,后gap个为一个数组,然后让这两个数组进行归并
		for (i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;
			//先判断求出来的区间是否有越界区间
			//end1越界或者begin2越界,则可以不归并了
			if ((end1 >= n) || (begin2 >= n))
			{
				break;
			}
			//此时end2越界,则归并时只需归并[begin2,n-1]区间即可
			if (end2 >= n)
			{
				end2 = n - 1;
			}
			int j = begin1;
			//归并操作
			while ((begin1 <= end1) && (begin2 <= end2))
			{
				if (arr[begin1] < arr[begin2])
				{
					tmp[j++] = arr[begin1++];
				}
				else
				{
					tmp[j++] = arr[begin2++];
				}
			}
			while (begin1 <= end1)
			{
				tmp[j++] = arr[begin1++];
			}
			while (begin2 <= end2)
			{
				tmp[j++] = arr[begin2++];
			}
		}
		//此时tmp辅助数组的数据为有序的,而arr数组中的数据还是无序的,所以要将tmp中的内容拷贝到arr中。
		//此时arr中从起始位置开始,让每gap个元素为一个数组,则这些数组都是有序的,
		memcpy(arr, tmp, sizeof(int) * n);
		//然后将这些数组每两组归并为一个更大的有序数组
		gap = gap * 2;
	}

	//释放辅助数组的空间
	free(tmp);
}

三、计数排序

1、计数排序基本思想

计数排序思想:计数排序又称为鸽巢原理,是对哈希直接定址法的变形应用。 操作步骤:

  1. 统计相同元素出现次数
  2. 根据统计的结果将序列回收到原来的序列中
    即创建一个数组用来统计每个数据出现的次数,然后排序就是按出现次数将这些数据再写回到原数组中。
    例如有如下一个数组。
    在这里插入图片描述
    我们再创建一个辅助数组tmp,该辅助数组的大小是这组数据的最大最小值之差+1。刚开始tmp数组中的值都初始化为0。
    在这里插入图片描述
    然后遍历arr数组,每当遍历一个元素,就将tmp[arr[i]]中的值+1,即代表遍历该元素的次数。
    在这里插入图片描述
    此时再遍历tmp数组,然后根据tmp数组中每个元素出现的次数n,将该元素再写入n个在arr数组中,此时arr数组中的元素就全都有序了。
    在这里插入图片描述
    上面的情况为最好的情况,即将每个数据绝对映射到tmp数组中(例如元素值为n,就直接在tmp[n]中记录该元素出现的次数)。但是当遇到下面的情况时,此时如果还使用绝对映射的话,那么辅助数组tmp会有很多空间浪费。所以此时我们就需要使用相对映射。例如有如下的数组,此时如果使用绝对映射的话,就需要建立一个长度为1010的辅助数组tmp,而且tmp数组前1000个空间没有有效数据存储,就会造成浪费。
    在这里插入图片描述
    此时可以先遍历一遍arr数组,找到最大值max和最小值min,然后就可以建一个max-min+1长度的数组tmp。
    在这里插入图片描述

然后再次遍历arr数组,并且将arr[i]-min作为tmp的下标,在tmp数组中记录arr[i]元素出现的次数,即每当遍历一个元素,就将tmp[arr[i]-min]++。
在这里插入图片描述

然后再将tmp中记录的数据写回到arr数组中,即arr[i]=i+min,其中tmp数组中记录该数据出现几次,就在arr数组中写入几次,此时得到的arr数组就为有序数组。
在这里插入图片描述

这种相对映射的方法也适合有负数出现的情况,例如有如下数组。
在这里插入图片描述
先遍历一遍arr数组,得到最大值max和最小值min,然后求出辅助数组长度为max-min+1,然后就创建一个辅助数组tmp,并且将tmp中全部初始化为0。
在这里插入图片描述

然后再次遍历arr数组,并且将arr[i]-min作为tmp的下标,在tmp数组中记录arr[i]元素出现的次数,即每当遍历一个元素,就将tmp[arr[i]-min]++。虽然arr[0]为-5,但是ar[[i]-(-5)=0,所以tmp[0]中存的就是-5出现的次数。
在这里插入图片描述

然后再将tmp中记录的数据写回到arr数组中,即arr[i]=i+min,而tmp[0]中记录了-5出现的次数,arr[0]=i+min=0+(-5)=-5。tmp数组中记录该数据出现几次,就在arr数组中写入几次,此时得到的arr数组就为有序数组。

在这里插入图片描述

2、计数排序代码实现

void CountSort(int* arr, int n)
{
	int min = arr[0];
	int max = arr[0];
	int i = 0;
	//选出arr中最大最小值
	for (i = 1; i < n; i++)
	{
		if (arr[i] < min)
		{
			min = arr[i];
		}
		if (arr[i] > max)
		{
			max = arr[i];
		}
	}
	//然后求出辅助数组tmp的长度
	int len = max - min + 1;
	//给辅助数组申请空间
	int* tmp = (int*)malloc(sizeof(int) * len);
	if (tmp == NULL)
	{
		perror("CountSort malloc fail");
		exit(-1);
	}
	//将辅助数组中都初始化为0
	memset(tmp, 0, sizeof(int) * len);
	//然后将arr数组中元素出现的次数记录到tmp数组中
	for (i = 0; i < n; i++)
	{
		tmp[arr[i] - min]++;
	}
	//回写 -- 即将数据再写入到arr数组中
	int j = 0;
	for (i = 0; i < len; i++)
	{
		//出现几次就写入几次
		while (tmp[i]--)
		{
			arr[j++] = i + min;
		}
	}

	free(tmp);
}

3、计数排序效率分析

通过上述可以看到,计数排序的时间复杂度最优的情况下为O(N),但是计数排序还需要O(N)的空间复杂度,所以计数排序适合范围集中,重复数据多的情况。
并且计数排序有很多局限性
1.如果是浮点数、字符串就不能使用计数排序了。
2.如果数据范围很大,那么空间复杂度就会很高,计数排序就不适合了。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/969182.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

大数据-玩转数据-Flink状态编程(上)

一、Flink状态编程 有状态的计算是流处理框架要实现的重要功能&#xff0c;因为稍复杂的流处理场景都需要记录状态&#xff0c;然后在新流入数据的基础上不断更新状态。 SparkStreaming在状态管理这块做的不好, 很多时候需要借助于外部存储(例如Redis)来手动管理状态, 增加了编…

顺式元件热图+柱状图

写在前面 本教程来自粉丝投稿&#xff0c;主要做得是顺式元件的预测和热图绘制。类似的教程&#xff0c;在我们基于TBtools做基因家族分析也做过&#xff0c;流程基本一致。我们前期的教程&#xff0c;主要是基于TBtools&#xff0c;本教程主要是基于纯代码,也是值得学习收藏的…

【人工智能】—_线性分类器、感知机、损失函数的选取、最小二乘法分类、模型复杂性和过度拟合、规范化

文章目录 Linear predictions 线性预测分类线性分类器感知机感知机学习策略损失函数的选取距离的计算 最小二乘法分类求解最小二乘分类矩阵解法一般线性分类模型复杂性和过度拟合训练误差测试误差泛化误差复杂度与过拟合规范化 Linear predictions 线性预测 分类 从具有有限离…

2022年03月 C/C++(七级)真题解析#中国电子学会#全国青少年软件编程等级考试

C/C编程&#xff08;1~8级&#xff09;全部真题・点这里 第1题&#xff1a;红与黑 有一间长方形的房子&#xff0c; 地上铺了红色、 黑色两种颜色的正方形瓷砖。你站在其中一块黑色的瓷砖上&#xff0c; 只能向相邻的黑色瓷砖移动。 请写一个程序&#xff0c; 计算你总共能够到…

Aqs的CyclicBarrier。

今天我们来学习AQS家族的“外门弟子”&#xff1a;CyclicBarrier。 为什么说CyclicBarrier是AQS家族的“外门弟子”呢&#xff1f;那是因为CyclicBarrier自身和内部类Generation并没有继承AQS&#xff0c;但在源码的实现中却深度依赖AQS家族的成员ReentrantLock。就像修仙小说…

Java 复习笔记 - 学生管理系统篇

文章目录 学生管理系统一&#xff0c;需求部分需求分析初始菜单学生类添加功能删除功能修改功能查询功能 二&#xff0c;实现部分&#xff08;一&#xff09;初始化主界面&#xff08;二&#xff09;编写学生类&#xff08;三&#xff09;编写添加学生方法&#xff08;四&#…

ref 操作 React 定时器

秒表 需要将 interval ID 保存在 ref 中&#xff0c;以便在需要时能够清除计时器。 import { useRef, useState } from "react";const SecondWatch () > {const [startTime, setStartTime] useState<any>(null);const [now, setNow] useState<any>…

Elasticsearch中RestClient使用

&#x1f353; 简介&#xff1a;java系列技术分享(&#x1f449;持续更新中…&#x1f525;) &#x1f353; 初衷:一起学习、一起进步、坚持不懈 &#x1f353; 如果文章内容有误与您的想法不一致,欢迎大家在评论区指正&#x1f64f; &#x1f353; 希望这篇文章对你有所帮助,欢…

如何将自己的镜像使用 helm 部署

本文分别从如下几个方面来分享一波 如何将自己的镜像使用 helm 部署 简单介绍一下 helm 使用自己写 yaml 文件的方式在 k8s 中部署应用 使用 helm 的方式在 k8s 中部署应用 简单介绍一下 helm Helm 是 Kubernetes 的包管理器&#xff0c;在云原生领域用于应用打包和分发 Hel…

12. 微积分 - 梯度积分

Hi,大家好。我是茶桁。 上一节课,我们讲了方向导数,并且在最后留了个小尾巴,是什么呢?就是梯度。 我们再来回看一下但是的这个式子: [ f x f y

信息系统项目管理师(第四版)教材精读思维导图-第八章项目整合管理

请参阅我的另一篇文章&#xff0c;综合介绍软考高项&#xff1a; 信息系统项目管理师&#xff08;软考高项&#xff09;备考总结_计算机技术与软件专业技术_铭记北宸的博客-CSDN博客 本章思维导图PDF格式 本章思维导图XMind源文件 目录 8.1 管理基础 8.2 管理过程 8.3 制定项…

LRU算法 vs Redis近似LRU算法

LRU(Least Recently Use)算法&#xff0c;是用来判断一批数据中&#xff0c;最近最少使用算法。它底层数据结构由Hash和链表结合实现&#xff0c;使用Hash是为了保障查询效率为O(1)&#xff0c;使用链表保障删除元素效率为O(1)。 LRU算法是用来判断最近最少使用到元素&#xf…

最短路Dijkstra,spfa,图论二分图算法AYIT---ACM训练(模板版)

文章目录 前言A - Dijkstra Algorithm0x00 算法题目0x01 算法思路0x02 代码实现 B - 最长路0x00 算法题目0x01 算法思路0x02 代码实现 C - 二分图最大匹配0x00 算法题目0x01 算法思路0x02 代码实现 D - 搭配飞行员0x00 算法题目0x01 算法思路0x02 代码实现 E - The Perfect Sta…

企业架构LNMP学习笔记11

Nginx配置文件的介绍&#xff1a; #nginx子进程启动用户 #user nobody; #子进程数量 一般调整为cpu核数或者倍数 worker_processes 1; #错误日志定义 #error_log logs/error.log; #error_log logs/error.log notice; #error_log logs/error.log info;#进程pid 存储文件…

ISO/IEC/ITU标准如何快速查找(三十九)

简介: CSDN博客专家,专注Android/Linux系统,分享多mic语音方案、音视频、编解码等技术,与大家一起成长! 优质专栏:Audio工程师进阶系列【原创干货持续更新中……】🚀 人生格言: 人生从来没有捷径,只有行动才是治疗恐惧和懒惰的唯一良药. 更多原创,欢迎关注:Android…

C++中的语法知识虚继承和虚基类

多继承(Multiple Inheritance)是指从多个直接基类中产生派生类的能力,多继承的派生类继承了所有父类的成员。尽管概念上非常简单,但是多个基类的相互交织可能会带来错综复杂的设计问题,命名冲突就是不可回避的一个。 多继承时很容易产生命名冲突,即使我们很小心地将所有类…

UDP和TCP协议报文格式详解

在初识网络原理(初识网络原理_蜡笔小心眼子&#xff01;的博客-CSDN博客)这篇博客中,我们简单的了解了一下TCP/IP五层网络模型,这篇博客将详细的学习一下五层网络模型中传输层的两个著名协议:UDP和TCP 目录 一, 传输层的作用 二, UDP 1,UDP协议的特点 2,UDP报文格式 三, TC…

【数据结构】如何设计循环队列?图文解析(LeetCode)

LeetCode链接&#xff1a;622. 设计循环队列 - 力扣&#xff08;LeetCode&#xff09; 目录 做题思路 只开辟 k 个空间 多开一个空间 代码实现 1. 循环队列的结构 2. 开辟空间 3. 判断空 4. 判断满 5. 队尾插入数据 6. 队头删除数据 7. 获取队头元素 8. 获取队尾元…

ElasticSearch第二讲:ES详解 - ElasticSearch基础概念

ElasticSearch第二讲&#xff1a;ES详解 - ElasticSearch基础概念 在学习ElasticSearch之前&#xff0c;先简单了解下ES流行度&#xff0c;使用背景&#xff0c;以及相关概念等。本文是ElasticSearch第二讲&#xff0c;ElasticSearch的基础概念。 文章目录 ElasticSearch第二讲…

【GoldenDict】win11牛津高阶英汉双解词典安装使用方法

【词典资源】 1&#xff08;本文章使用的版本&#xff09;牛津高阶&#xff08;第10版 英汉双解&#xff09; V11.8&#xff1a; https://pan.baidu.com/s/11272Cldde_2UttQkWS2MlQ 提取码&#xff1a;0p3j 2&#xff08;另一版本&#xff09;第十版 v13.2&#xff1a; ht…