《数据结构》(六)八大排序(下)

news2024/11/26 12:45:39

承接上篇的八大排序,今天本篇文章主要讲归并排序,冒泡排序,快速排序(挖坑,左右指针,前指针)和计数排序


八大排序

  • 交换排序
    • 冒泡排序
      • 冒泡排序思想
      • 代码
      • 冒泡排序总结
    • 快速排序
      • 快速排序思想
      • 三数取中
        • 快速排序之挖坑法
          • 挖坑法代码
        • 快速排序之左右指针法
          • 左右指针法代码
        • 快速排序之前后指针法
          • 前后指针法代码
      • 快速排序总结
  • 归并排序
    • 归并排序思想
    • 代码
    • 归并排序总结
  • 计数排序
    • 计数排序思想
    • 代码
    • 计数排序总结
  • 排序算法复杂度及稳定性分析
  • 结语

交换排序

基本思想: 所谓交换,就是根据序列中两个记录键值的比较结果来对换这两个记录在序列中的位置;
交换排序的特点是: 将键值较大的记录向序列的尾部移动,键值较小的记录向序列的前部移动。

冒泡排序

冒泡排序思想

基本思想:
重复遍历序列,依次比较相邻的两个元素,如果不是按照特定的顺序那么就交换,直到最终序列为特定的顺序即可。 冒泡排序之所以被称为冒泡,就是其排序顺序的原理就像气泡上升一样,大的泡泡先浮上水面,小的泡泡浮上水面就慢。
整体步骤:
第一趟让最大的数冒到最后,第二趟将次大的数冒到最后…直到序列有序为止, 所以我们就知道要用到双层循环了,外层循环确定比较趟数(n-1),内层循环确定每趟比较次数(n-j-1)。

在这里插入图片描述

代码

//交换
void Swap(int*p1,int*p2)
{
	int* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//冒泡排序
void BubbleSort(int* a, int n)
{
	//方法一:
	for (int j = 0; j < n; ++j)//比较几轮
	{
		int enchange = 0;
		for (int i = 1; i < n-j; ++i)//将数组中最大值冒到最后面
		{//这里i=1,如果i=0的话要注意下面交换函数中会存在越界访问
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				enchange = 1;
			}
		}
		//这里用了有一个判断是对原冒泡排序的一个优化,原冒泡排序如果待排序列接近有序,难道我们还要依次去比较吗?
		//因此我们定义一个enchange,如果发生比较,那么enchange的值为1,如果没有比较,则enchange为0,就break
		if (enchange == 0)//如果enchange等于0的话,就结束循环,就是看数组是否有序
		{
			break;
		}
	}

	//方法二:这个方法使用while做了外层循环,本质一样
	/*int end = n;
	while (end > 0)
	{
		for (int i = 1; i < end; ++i)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
			}
		}
		--end;
	}*/
}
void TestBubbleSort()
{
	int a[] = { 3, 5, 2, 7, 8, 6, -1, 9, 9, 4, 0 };
	BubbleSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

冒泡排序总结

  • 冒泡排序是一种非常容易理解,而且非常简单的排序;
  • 时间复杂度:O(N^2);
  • 空间复杂度:O(1);
  • 稳定性:稳定。

快速排序

快速排序思想

快速排序是Hoare于1962年提出的一种二叉树结构的交换排序方法。(我们果然是站在巨人的肩膀上😛)
其本思想: 任取待排序元素序列中的某元素作为基准值,首趟让这个基准值放到它相应地位置,并采用分治的思想按照该排序码将待排序集合分割成两子序列,左子序列中所有元素均小于基准值,右子序列中所有元素均大于基准值,然后左右子序列递归重复该过程,直到所有元素都排列在相应位置上为止。

三数取中

问题: 从上面《快速排序思想》中知道了快速排序是在序列中选出一个元素作为基准值(一般是首元素,或者尾元素),但是如果我们选的元素是最小的或者是最大的呢?😵😵😵
答: 那么将存在一些弊端,因此我们引入了三数取中的思想: 当我们知道这个序列的首和尾之后,我们可以轻易地找到中间元素,将首,中,尾三个元素中,选一个中间值作为基准值,这样就可以提高快速排序的效率。下面代码中还有小区间优化,大家在理解快速排序的基础上可以试着将三数取中和小区间优化也了解一下。

快速排序之挖坑法

这里就讲解部分先不按照三数取中和小区间优化,大家理解之后可以进一步按照代码学习三数取中和小区间优化。😋😋😋

单趟步骤:

  • 1.把最左边或者最右的位置的值保存到key中,这个地方形成坑位(pivot);
  • 2.定义两个指针left和right,分别指向序列首元素和尾元素;
  • 3.让right先从右向左走,找到比key小的位置停下来,并将这个元素放到坑位,然后自己形成新的坑;
  • 4.再让left从左向右走,找到比key大的位置停下来,并将这个元素放到坑位,然后自己形成新的坑。
  • 5.重复步骤3和步骤4,当left和right相遇的时候,把key的值放到当时的坑位。
    在这里插入图片描述

整体步骤:

  • 1.当单趟排序完成之后,用分治的思想将序列分为[left,key-1] key [key +1,right]三个子区间;
  • 2.分别递归将[left,key-1] 和 [key +1,right]排序,如果分出的区间还不是有序,那就再分区间,进行递归,以此往复,直到待排子区间只有一个元素,则序列有序。

在这里插入图片描述

挖坑法代码
//交换
void Swap(int*p1,int*p2)
{
	int* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//三数取中--为了解决我们key选择的数不是最大,也不是最小的
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])//如果左小于中间
	{
		if (a[mid] > a[right])//如果左小于中间,中间大于右,则返回中间
		{
			return mid;
		}
		else if (a[left] > a[right])//如果左小于中间,左大于右,则返回左
		{
			return left;
		}
		else
		{
			return right;//如果左小于中间,中间大于右,则返回右
		}
	}
	else //a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
int PartSort1(int* a, int left, int right)
{
	int index = GetMidIndex(a, left, right);//三数取中
	Swap(&a[left], &a[index]);
	int begin = left, end = right;
	int pivot = begin;
	int key = a[begin];
	//单趟排序
	//单趟排序时间复杂度是O(N)-begin从左向右走,end从右向左走
	while (begin < end)
	{
		//右边找小,放到左边
		while (begin < end && a[end] >= key)
			--end;
		//小的放到左边的坑里,自己形成新的坑位
		a[pivot] = a[end];
		pivot = end;

		//右边找大
		while (begin < end && a[begin] <= key)
			++begin;
		//大的放到右边的坑里,自己形成新的坑位
		a[pivot] = a[begin];
		pivot = begin;
	}
	//把小的放到pivot的左边,大的放到pivot的右边后,把key的值放到数组pivot的位置
	pivot = begin;
	a[pivot] = key;

	//返回的是坑的位置
	return pivot;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//挖坑法
	int keyIndex = PartSort1(a, left, right);
	//一趟之后把数组分段
	//[left,right]
	//[left,keyIndex-1] keyIndex [keyIndex +1,right]
	// 左子区间和右子区间有序,我们就有序了,如果让他们有序呢? 分治递归
	
	//小区间优化,很明显发现,递归一段时间后,后面的几层会占用大部分的递归次数,所以引进了一个小区间优化算法
	//小区间优化,就是当递归进行到一定层数之后,后面几层改用其他排序的方法,冒泡,堆排序,希尔都是不行的,再考虑到剩下几层
	//的数据量也不大,就直接用插入排序
	if (keyIndex - 1 - left > 13)
	{
		QuickSort(a, left, keyIndex - 1);//递归pivot的左边
	}
	else
	{
		//这里小区间为什么是a+left?,因为我们如果右递归,数组肯定不是从大数组的首元素开始的
		InsertSort(a + left, keyIndex - 1 - left + 1);
		//这里的为什么是piovt-1-left+1?为什么要加1呢?--假如我们数组是[0,9],这个数组里面是10个元素,而9-0等于9,所以加1
		//(pivot - 1 - left + 1)为什么减left和(a + left)是一样的意思
	}
	if (right - (keyIndex + 1) > 13)
	{
		QuickSort(a, keyIndex + 1, right);//递归pivot的右边
	}
	else
	{
		InsertSort(a + keyIndex +1, right-(keyIndex +1)+1);
	}
}
void TestQuickSort()
{
	int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
	QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);
}

快速排序之左右指针法

单趟步骤:

  • 1.先选出一个元素保存到key中,再定义两个指针left和right,left从左向右走,right从右向左走;
  • 2.先让right从右向左走,找到比key小的位置停下,再让left从左向右找到比key大的位置停下,;
  • 3.交换left和right位置的元素,然后继续让left向右走,right向左走重复步骤2和3;
  • 4.当left和right相遇的时候停下来,将key保存的元素和相遇位置的元素交换。
    在这里插入图片描述

整体步骤:

  • 接下来的步骤和挖坑法的一样,分段并递归使其有序即可。
左右指针法代码
//交换
void Swap(int*p1,int*p2)
{
	int* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
//快速排序更进--三数取中 
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])//如果左小于中间
	{
		if (a[mid] > a[right])//如果左小于中间,中间大于右,则返回中间
		{
			return mid;
		}
		else if (a[left] > a[right])//如果左小于中间,左大于右,则返回左
		{
			return left;
		}
		else
		{
			return right;//如果左小于中间,中间大于右,则返回右
		}
	}
	else //a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
//左右指针法
int PartSort2(int* a, int left, int right)
{
	//三数取中
	int index = GetMidIndex(a, left, right);//为了解决我们key选择的数不是最大,也不是最小的
	Swap(&a[left], &a[index]);
	int begin = left, end = right;
	int keyi = begin;
	while (begin < end)
	{
		//从右到左找小
		while (begin<end && a[end]>=a[keyi])
		{
			--end;
		}
		//从左到右找大
		while (begin < end && a[begin] <= a[keyi])
		{
			++begin;
		}
		//begin是找大,end是找小,当两个循环跳出就是找到了,然后交换
		Swap(&a[begin], &a[end]);
	}
	//当begin和end相遇的时候,就停止循环,再将相遇位置和keyi交换就行了
	Swap(&a[begin], &a[keyi]);

	return begin;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//左右指针法
	int keyIndex = PartSort2(a, left, right);
	if (keyIndex - 1 - left > 13)
	{
		QuickSort(a, left, keyIndex - 1);//递归pivot的左边
	}
	else
	{
		InsertSort(a + left, keyIndex - 1 - left + 1);
	}
	if (right - (keyIndex + 1) > 13)
	{
		QuickSort(a, keyIndex + 1, right);//递归pivot的右边
	}
	else
	{
		InsertSort(a + keyIndex +1, right-(keyIndex +1)+1);
	}
}
void TestQuickSort()
{
	int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
	//递归
	QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);
}

快速排序之前后指针法

单趟步骤:

  • 1.先选出一个元素保存到key中,定义两个指针分别是prev和cur,分别指向序列首元素和prev后一个元素;
  • 2.如果cur指向的元素小于key,prev和cur向后移动;
  • 3.如果cur指向的元素大于key,则prev不动,cur继续后移找小,如果找到了,就将prev向后移动一位,并将移动后的位置的元素和cur指向的元素交换;
  • 4.然后cur继续向后走,并重复步骤2和3;
  • 5.如果cur走出序列,则将key保存的元素与prev指向元素交换即可。
    在这里插入图片描述

整体步骤:

  • 步骤和上面两个算法一样
前后指针法代码
//交换
void Swap(int*p1,int*p2)
{
	int* tmp = *p1;
	*p1 = *p2;
	*p2 = tmp;
}
int GetMidIndex(int* a, int left, int right)
{
	int mid = (left + right) >> 1;
	if (a[left] < a[mid])//如果左小于中间
	{
		if (a[mid] > a[right])//如果左小于中间,中间大于右,则返回中间
		{
			return mid;
		}
		else if (a[left] > a[right])//如果左小于中间,左大于右,则返回左
		{
			return left;
		}
		else
		{
			return right;//如果左小于中间,中间大于右,则返回右
		}
	}
	else //a[left] > a[mid]
	{
		if (a[mid] > a[right])
		{
			return mid;
		}
		else if (a[left] < a[right])
		{
			return left;
		}
		else
		{
			return right;
		}
	}
}
//前后指针法
//cur找小,每次遇到比keyi小的值就停下来,++prev,交换prev和cur位置的值,等到cur走出这个数组后,将prev位置的值和keyi的值交换
int PartSort3(int* a, int left, int right)
{
	//三数取中
	int index = GetMidIndex(a, left, right);//为了解决我们key选择的数不是最大,也不是最小的
	Swap(&a[left], &a[index]);
	int keyi = left;
	int prev = left, cur = left + 1;
	while (cur <= right)
	{
		/*if (a[cur] < a[keyi])
		{
			++prev;
			Swap(&a[prev], &a[cur]);
		}*/
		if (a[cur] < a[keyi] && ++prev != cur)//这串代码与上面代码的区别就是防止自己和自己交换,浪费时间
		{
			++prev;
			Swap(&a[prev], &a[cur]);
		}
		++cur;
	}
	Swap(&a[keyi], &a[prev]);
	return prev;
}
void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//前后指针法
	int keyIndex = PartSort3(a, left, right);
	if (keyIndex - 1 - left > 13)
	{
		QuickSort(a, left, keyIndex - 1);//递归pivot的左边
	}
	else
	{
		InsertSort(a + left, keyIndex - 1 - left + 1);
	}
	if (right - (keyIndex + 1) > 13)
	{
		QuickSort(a, keyIndex + 1, right);//递归pivot的右边
	}
	else
	{
		InsertSort(a + keyIndex +1, right-(keyIndex +1)+1);
	}
}
void TestQuickSort()
{
    int a[] = { 49, 38, 65, 97, 76, 13, 27, 49 };
	QuickSort(a, 0, sizeof(a) / sizeof(int) - 1);
}

快速排序总结

  • 为啥敢叫快速排序,因为它真牛批,1962年沿用到现在
  • 时间复杂度:O(N*logN);
  • 空间复杂度:O(logN);
  • 稳定性:不稳定

归并排序

归并排序思想

归并排序是建立在归并操作上的一种有效的排序算法,该算法是采用分治法的一个非常典型的应用。
基本思想: 将已有序的子序列合并,得到完全有序的序列;即先使每个子序列有序,再使子序列段间有序。若将两个有序表合并成一个有序表,称为二路归并。
在这里插入图片描述

代码

//归并排序
//假设左半区间有序,右半区间有序,归并,依次对比取小的放到新的临时数组,
//最后把左右两个区间中剩余数据的区间的所有拷贝到临时数组后面,再把临时数组中的数组拷贝到原数组
void _MergeSort(int* a, int left, int right,int* tmp)
{
	if (left >= right)
		return;
	int mid = (left + right) >> 1;//右移一位相当于除2
	//这时区间被分为[left,mid],[mid+1,right]
	//假设[left,mid],[mid+1,right]有序,那么我们就可以归并
	_MergeSort(a, left, mid, tmp);
	_MergeSort(a, mid + 1, right, tmp);

	//归并
	int begin1 = left, end1 = mid;
	int begin2 = mid + 1, end2 = right;
	int index = left;
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[index++] = a[begin1++];
		}
		else
		{
			tmp[index++] = a[begin2++];
		}
	}
	while (begin1 <= end1)
	{
		tmp[index++] = a[begin1++];
	}
	while (begin2 <= end2)
	{
		tmp[index++] = a[begin2++];
	}
	//拷贝回去--把临时数组内的元素拷贝到原数组中
	for (int i = left; i <= right; ++i)
	{
		a[i] = tmp[i];
	}
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	_MergeSort(a, 0, n - 1, tmp);

	free(tmp);
}
void TestMergeSort()
{
	int a[] = { 10, 6, 7, 1, 3, 9, 4, 2 };
	//递归归并
	MergeSort(a, sizeof(a) / sizeof(int));
}

归并排序总结

  • 归并的缺点在于需要O(N)的空间复杂度,归并排序的思考更多的是解决在磁盘中的外排序问题;
  • 时间复杂度:O(N*logN);
  • 空间复杂度:O(N);
  • 稳定性:稳定。

计数排序

计数排序思想

基本思想:通过统计数组中相同元素出现的次数,然后通过统计的结果将序列放回到原来的序列中。 是一种牺牲空间换时间的算法。 较为简单,看代码就能看懂😎。

代码

void CountSort(int* a,int n)
{
	int max = a[0], min = a[0];
	for (int i = 0; i < n; ++i)//找出最大的值和最小的值
	{
		if (a[i] > max)
		{
			max = a[i];
		}
		if (a[i] < min)
		{
			min = a[i];
		}
	}

	int range = max - min + 1;//求出范围
	int* count = (int*)malloc(sizeof(int) * range);
	memset(count, 0, sizeof(int) * range);//将开辟的数组初始化为0,也就是出现了0次

	//统计次数
	for (int i = 0; i < n; ++i)
	{
		count[a[i]-min]++;//相对映射
	}
	int j = 0;
	for (int i = 0; i < range; ++i)
	{
		while (count[i]--)
		{
			a[j++] = i + min;
		}
	}
	free(count);
}
void TestCountSort()
{
	int a[] = { 10, 6, 7, 1, 3, 9, 4, 2, 10, 6, 7, 1, 3, 9, 4, 2 };
	CountSort(a, sizeof(a) / sizeof(int));
	PrintArray(a, sizeof(a) / sizeof(int));
}

计数排序总结

  • 计数排序只适用于数据范围较集中的序列的排序,若待排序列的数据较分散,则会造成空间浪费,并且计数排序只适用于整型排序,不适用与浮点型排序;
  • 时间复杂度O(2N+range)=O(N+range);
  • 空间复杂度O(range)。

排序算法复杂度及稳定性分析

在这里插入图片描述


结语

😊😊😊数据结构到这里算是基本完结了,接下来会将快速排序和归并排序的非递归写一下,后续有空会将串、广义表等更新出来。😚😚😚

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

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

相关文章

量化股票查询代码是什么?

量化股票查询代码是什么&#xff1f;接下来用一些代码来分析一下&#xff0c;如下&#xff1a; 做空95&#xff1a;HHV((HIGHLOWOPEN2*CLOSE)/5H-L,5),COLORBLUE;做空68: HHV((HIGH-LOWOPEN2*CLOSE)/5*2-L,5),COLORRED&#xff1b; 平衡点&#xff1a;LLV((HIGHLOWOPEN2*CLOSE…

狗厂员工来面试本想难为一下,问他内存溢出,结果被虐得连console.log也不敢写了

这次说到的面试题是关于node服务端内存溢出的问题&#xff0c;狗厂员工来面试本想难为一下&#xff0c;现在我连console.log也不敢写了 关于这道node内存溢出的问题&#xff0c;大哥从以下几个方面讲的&#xff0c;讲完我觉得自己得到了升华&#xff0c;现在搞得连代码也快不敢…

AI人脸检测/安全帽检测智能分析网关告警消息配置——微信告警消息配置

AI智能分析网关内置多种深度学习算法&#xff0c;可支持对接入的多路视频流进行智能检测、智能识别等&#xff0c;包括人脸检测与识别、车辆检测与识别、车牌识别、烟火识别、安全帽识别、区域入侵检测等。将智能分析网关与EasyCVR视频融合平台联合使用&#xff0c;可实现智能告…

Linux命令从入门到实战 ---- 用户管理命令

文章目录useradd添加新用户passwd设置用户密码id查看用户是否存在查看创建了哪些用户su切换用户userdel删除用户who查看登录用户信息sudo设置普通用户具有root权限用户组groupadd 新增用户组usermod修改用户groupdel删除用户组groupmod修改用户组总结useradd添加新用户 将usera…

安卓学习笔记5.3 按钮、图像视图与图像按钮

文章目录零、本讲学习目标一、导入新课二、新课讲解&#xff08;一&#xff09;按钮控件1、继承关系图2、常用属性&#xff08;二&#xff09;图像视图1、继承关系图2、常用属性&#xff08;三&#xff09;图像按钮1、继承关系图2、常用属性&#xff08;四&#xff09;教学案例…

vue无需改动代码的SEO【百度爬取】优化--puppeteer(详细流程)

vue无需改动代码的SEO优化–puppeteer&#xff08;详细流程&#xff09; 目录vue无需改动代码的SEO优化--puppeteer&#xff08;详细流程&#xff09;一级目录二级目录三级目录一、安装puppeteer&#xff1a;npm install puppeteer --save安装依赖二、编写puppeteer服务js文件p…

DDD领域驱动设计基础

什么领域驱动模型 领域驱动模型一种设计思想&#xff0c;我们又称为DDD设计思想。是一种为了解决传统设计思想带来的维护困难&#xff0c;沟通困难和交互困难而产生的一种新的思想。 架构模式的演进 单体架构 采用面向对象的设计方法&#xff0c;系统包括业务接入层、业务逻…

Eclipse切JRE环境后如何恢复- Unrecognized option: --enable-preview

场景 使用switch 新特性 配合 lambda 练习小案例 // 需求&#xff1a; 1 2 3 -> 一、二、 三 int num 1; switch ( num) {// jdk13 可以缺省 break 并且 单语句可以省略 花括号 case 1 -> { System.out.println("一"); }case 2 -> System.out.p…

[附源码]计算机毕业设计JAVAjsp宠物店管理系统

[附源码]计算机毕业设计JAVAjsp宠物店管理系统 项目运行 环境配置&#xff1a; Jdk1.8 Tomcat7.0 Mysql HBuilderX&#xff08;Webstorm也行&#xff09; Eclispe&#xff08;IntelliJ IDEA,Eclispe,MyEclispe,Sts都支持&#xff09;。 项目技术&#xff1a; SSM mybat…

Mybatis-Plus知识点[MyBatis+MyBatis-Plus的基础运用]

目录 前言 一、了解Mybatis-Plus 1.简介 2.Mybatis-Plus具有的特性 3.支持数据库 4.框架结构 5.官网链接 二、快速开始 2.1.创建数据库以及表 2.2.创建工程 2.3 MybatisMybatis-Plus的使用 2.3.1创建一个itcast-mybatis-plus-simple的maven项目 2.3.2写UserMapper接口 2.3.3写U…

北京化工大学数据结构2022/11/3作业 题解

目录 问题 A: 二叉树非递归前序遍历-附加代码模式 问题 B: 二叉树非递归中序遍历-附加代码模式 问题 C: 二叉树非递归后序遍历-附加代码模式 问题 D: 求二叉树中序遍历序根节点的下标 问题 E: 根据前序中序还原二叉树 问题 F: 算法6-12&#xff1a;自底向上的赫夫曼编码 …

ServletConfig和ServletContext接口

一、ServletConfig接口详解 1、简介 Servlet 容器初始化 Servlet 时&#xff0c;会为这个 Servlet 创建一个 ServletConfig 对象&#xff0c;并将 ServletConfig 对象作为参数传递给 Servlet 。通过 ServletConfig 对象即可获得当前 Servlet 的初始化参数信息。一个 Web 应用中…

微电网优化调度(风、光、储能、柴油机)(Python代码实现)

&#x1f4a5;&#x1f4a5;&#x1f4a5;&#x1f49e;&#x1f49e;&#x1f49e;欢迎来到本博客❤️❤️❤️&#x1f4a5;&#x1f4a5;&#x1f4a5; ​ &#x1f3c6;博主优势&#xff1a;&#x1f31e;&#x1f31e;&#x1f31e;博客内容尽量做到思维缜密&#xff0c;逻…

【Linux命令】文件和目录权限

【Linux命令】文件和目录权限 权限查看 众所周知&#xff0c;可以使用 ls -l 来查看文件和目录的详细信息&#xff0c;那么输出的东西是什么呢&#xff1f; 我们先来看 文件类型&#xff1a; -&#xff1a;普通文件&#xff1b;d&#xff1a;目录文件&#xff1b;b&#xff…

网络协议:TCP三次握手与四次挥手

本篇内容包括&#xff1a;TCP/IP 传输协议&#xff08;TCP/IP 传输协议简介&#xff0c;IP 协议&#xff0c;UDP 协议&#xff0c;TCP 协议介绍&#xff09;&#xff0c;TCP 的三次握手、TCP 的四次挥手 以及 TCP 协议是怎么保证有效传输等内容。 一、TCP/IP 传输协议 1、TCP/…

【仿牛客网笔记】 Redis,一站式高性能存储方案——Redis入门

Redis可以开发对性能要求较高的功能。还可以利用Redis重构我们现有的功能。 NoSQL关系型数据库之外的统称。 快照有称为RDB 以快照的形式 不适合实时的去做&#xff0c;适合一段时间做一次。 日志又称AOF 以日志的形式每执行一次就存入到硬盘中&#xff0c;可以做到实时的存储以…

JAVA外卖订餐系统毕业设计 开题报告

本文给出的java毕业设计开题报告&#xff0c;仅供参考&#xff01;&#xff08;具体模板和要求按照自己学校给的要求修改&#xff09; 选题目的和意义 目的&#xff1a;本课题主要目标是设计并能够实现一个基于java的外卖点菜系统&#xff0c;管理员通过后台添加菜品&#xf…

卷积神经网络CNN

卷积神经网络CNN CNN通常用于影像处理 为什么需要CNN 为什么需要CNN&#xff0c;我用普通的fully connected的反向传播网络进行图像训练会怎样 需要过多参数 假设一张彩色的图为100100的&#xff0c;那么像素点就是1001003&#xff0c;那么输入层为三万维 假设下一层隐含层有…

移动Web:Less 预处理及Koala工具

css 预处理器&#xff0c;后缀名为 .less。 less 代码无法被浏览器识别&#xff0c;实际开发需要转换成 css&#xff0c;使用 liink 标签引入 css 文件。 插件工具 Easy Less VS Code 内置插件&#xff08;less 文件保存自动生成 css 文件&#xff09; 更改编译后 css 存储路径…

华清远见11.7

系统移植开发阶段部署 1.准备文件&#xff0c;由于内核只支持安全的启动模式&#xff0c;要准备u-boot镜像文件u-boot-stm32mp157a-fsmp1a-trusted.stm32 TF-A镜像文件tf-a-stm32mp157a-fsmp1a-trusted.stm32 linux内核镜像文件uImage和stm32mp157a-fsmp1a.dtb 根文件系统r…