排序算法的实现(插入,希尔,选择,冒泡,堆排,快排)

目录

1.选择排序

2.冒泡排序

3.堆排序

4.插入排序

5.希尔排序

6.快排

6.1快排的优化

6.2快排(双指针法)

6.3快排(非递归)

7.归并排序

7.1归并非递归

8.计数排序


1.选择排序

对n个元素进行选择排序,我们可以遍历一轮找出最大值放在末尾,直到循环n-1次。

为了提高效率,我们可以同时找出最大值和最小值,分别放在末尾和开头。

//选择排序
void SelsectSort(int* a,int n)
{
	int begin=0,end=n-1;//begin要参与排序元素的第一个 end参与排序元素的最后一个 
	while(begin<end)
	{
		int maxi=begin,mini=begin,i;//maxi记录最大值下标 mini记录最小值的下标 
		for(i=begin;i<=end;i++)
		{
			if(a[maxi]<a[i]) maxi=i;
			if(a[mini]>a[i]) mini=i;
		}
		Swape(&a[maxi],&a[end]);//最大值放最后面 
		if(mini==end) mini=maxi;//如果最后面正好是最小值 那最小值会跑到下标为maxi上 
		Swape(&a[mini],&a[begin]);//最小值放最前面 
		begin++;//把已经排好的退出循环 
		end--;
	}
}

2.冒泡排序

左边和右边比较,大于就交换。每循环一趟最大值都会出现在最右边。

//冒泡排序
void BubbleSort(int* a,int n)
{
	int i,j;
	for(i=0;i<n-1;i++)//循环趟数 
	{
		for(j=0;j<n-1-i;j++)//-i减去排好的 
		{
			if(a[j]>a[j+1]) Swape(&a[j],&a[j+1]); 
		}
	}
}

3.堆排序

要实现堆排序,我们先要用向下调整对数组建立堆结构。(向下调整比向上调整效率高)

实现升序就建大堆,堆顶为最大值,堆顶与最后一个元素交换,然后把最后一个元素(也就是最大值)剔除,再进行建堆。一直循环直到只剩堆顶元素。

同样降序就建小堆。

//向下调整(大堆) 根节点下标0
void AdjustDown(HPDataType*a,int n,int parent)//n为元素个数,最后一个元素下标为n-1 
{   
    int child=parent*2+1;//找当前父母孩子 

	while(child<n)
	{
		if(child+1<n&&a[child]<a[child+1]) child++;//找最大的孩子 
			
		if(a[parent]<a[child])//大的值向上调 
		{
			change(&a[parent],&a[child]); 
		}
        else break;//父母节点>=孩子节点 符合堆结构 不用继续向下调整
		parent=child;//继续向下进入下一层循环 
		child=parent*2+1;
	}
} 
// 对数组进行堆排序(升) 
void HeapSort(int* a, int n)
{   int i;
   		for(i=(n-1-1)/2;i>=0;i--)//n-1最后一位元素下标 (n-1-1)/2找最后一位结点的父母下标 
	{                          
		AdjustDown(a,n,i);//向下交换 建堆 
	}
   int end=n-1;//end最后一个元素下标 
   while(end>0)
   {
   	change(&a[0],&a[end]);//最大元素与最后一个元素交换 
    AdjustDown(a,end,0);//向下交换找出最大值 时间复杂度logn (因为end传过去是被当作元素个数来看待,最后一个元素不会参与堆的再构建)
	end--;//最后一个元素排完,--脱离堆结构 
   }
   //循环再找次大 并排到堆结构的最后一位 
}

4.插入排序

对于第n个元素,我们先用tmp记录它的值,如果比前一个元素小,前一个元素就后移,直到大于等于前一个数,或者到0下标结束,最后在结束位置插入tmp。

插入排序的基本思路:
从第二个元素开始,将当前元素与前面已经排好序的部分进行比较。
找到合适的位置,将当前元素插入到该位置。
重复这个过程,直到整个序列有序。
插入排序的过程
1.以数组 [5, 2, 9, 1, 5, 6] 为例,插入排序的过程如下:

从第二个元素 2 开始,将其与前面的元素 5 比较。2 小于 5,所以交换它们。
2.数组变成 [2, 5, 9, 1, 5, 6]
处理第三个元素 9,9 大于 5,不需要交换。
3.数组仍然是 [2, 5, 9, 1, 5, 6]
处理第四个元素 1,将其与前面的元素逐一比较,直到找到合适的位置。1 小于所有的元素,所以将其放在最前面。
4.数组变成 [1, 2, 5, 9, 5, 6]
处理第五个元素 5,与前面的元素逐一比较,找到合适位置,将其插入到 [2, 5, 9] 和 6 之间。
5.数组变成 [1, 2, 5, 5, 9, 6]
处理第六个元素 6,将其插入到 9 和 5 之间。
6.数组变成 [1, 2, 5, 5, 6, 9]
最终,整个数组变成了 [1, 2, 5, 5, 6, 9],即排序完成。

// 插入排序
void InsertSort(int* a, int n)
{
	int i;
	for(i=0;i<n-1;i++)//排n个元素 循环n-1次 
	{
		int end=i;//0~end有从小到大的顺序 
		int tmp=a[end+1];//记录a[end+1]的值 
		while(end>=0)
		{
			if(tmp<a[end])//比后面小就覆盖(本质还是互换) 
			{
				a[end+1]=a[end]; 
				end--;
			}
			else break;//比后面大就终止 
		}
		a[end+1]=tmp;//在终止位置上存入tmp 
	}
}

5.希尔排序

希尔排序是插入排序变化来的,希尔排序可以分为预排序 细排。

预排序的目的是把无序的数组变成接近有序。我们可以把一组数组分为多组,在同一组中每个元素在原数组的下标之间的距离(gap)都是一样的,然后对每一组进行插入排序,使原数组接近有序。

细排通过插入排序(gap==1)把接近有序的数组变成有序。

//希尔排序 
void ShellSort(int* a, int n)
{
  int gap=n,i;
  while(gap>0)
  { 
  	gap/=2;//最终gap变1 
	for(i=0;i<n-gap;i++)//每组轮流排一次 
	{   
		int end=i; //end在一组内最后一个有序元素的下标 
		int tmp=a[end+gap];//tmp一组内最后一个有序元素的下一个元素 
		while(end>=0)
		{
			if(tmp<a[end])
			{
				a[end+gap]=a[end];//比后面小就覆盖(本质还是互换) 
				end-=gap;//比较下一个元素 
			}
			else break;//比后面大就终止
		}
		a[end+gap]=tmp;//在终止位置上存入tmp 
	} 
  }
}

时间复杂度大概为n^1.3。

6.快排

快排本质是利用二叉树递归的思想。

首先找一个值设为key(一般为首尾元素),假设我们以第一个元素为key,先从最后一个元素开始找比key小的值,找到就停下,然后再从第一个元素开始找比key大的元素,找到就和比key小的值交换,一直循环。(如果以最后一个元素为key,就先从第一个元素开始找)

直到两者相遇,相遇结点的值再和key交换。此时key左边的值都比它小,右边的值都比它大。

(如果相遇结点的值比key大还交换吗?结论:相遇结点的值永远小于等于key 原因在代码中)

我们可以把key结点看作根,它的左边看作左子树,右边看作右子树。左右子树分别递归循环,排好中间位置的元素,直到子树只有一个结点,或者为空。

//快速排序
void QuitSort(int *a,int begin,int end)//begin第一个元素 end最后一个元素下标 
{
	int ki=begin,bi=begin,ei=end;//ki记录key值的下标 便于后面交换 
	if(begin>=end) return;//子树为空或者只有一个结点,直接返回 
	while(begin<end)
	{
		if(a[end]>a[ki]) end--;//key对面的下标先动(一般以起点/终点为key) 找比key小的值 
		if(a[begin]<a[ki]) begin++;//找比key大的值 
		Swape(&a[end],&a[begin]);
	} 
	Swape(&a[begin],&a[ki]);//此时key左边的值都比key小,右边都比key大 
	QuitSort(a,bi,ki-1);//遍历左子树 对key左边的值进行排序 
	QuitSort(a,ki+1,ei);//遍历右子树 对key右边的值进行排序
}
//begin和end相遇结点的值一定不大于key(从小到大排)
//1.begin碰end 此时end是不动的 说明a[end]<key
//2.end碰begin 这又可以分为2种情况
//(1)end和begin相遇前至少进行过一次交换 交换完后end先动碰到begin 因为交换过a[begin]<key
//(2)end和begin相遇前没有进行过交换 end会一直--直到碰到begin  此时begin和end同时指向key 

6.1快排的优化

1.取key随机性高,容易取到极端值

对与这个问题,我们可以采用三目取中法来解决。在数组开头 结尾 中间 3个值中取一个中间值并作为key。

我们写一个在3个数中返回中间值下标的函数就可以了

​
//三目取中 
int GetMidi(int *a,int begin,int end)
{
	int midi=(begin+end)/2;
	if(a[midi]<a[begin])
	{
		if(a[end]<a[midi]) return midi;
		else if(a[begin]>a[end]) return end;//此时midi是最小值 返回较小的 
		else return begin;
	} 
	else  //a[midi]>=a[begin]
	{
		if(a[end]>a[midi]) return midi;
		else if(a[end]>a[begin]) return end;//此时midi是最大值 返回较大的 
		else  return begin;
	}
}

​

2.函数递归太多 栈内存空间消耗大

我们知道在满二叉树中最后一层结点个数大约占整个二叉树的%50,最后二层占%75。

而在快排中如果需要排序的个数太少,没有必要去建立栈来排,我们可以直接采用插入排序解决。

再加上三目取中法,我们就可以写出下面的函数。

//优化快排 
void ImproveQuitSort(int *a,int begin,int end)//begin第一个元素 end最后一个元素下标 
{   
    if(end-begin+1<10)//减少建栈(内存) 量少的直接用插入解决 
    {
    	InsertSort(a,end-begin+1);
    	return;
    }
	int ki=GetMidi(a,begin,end),bi=begin,ei=end;//三目取中ki取中间值的下标
	Swape(&a[begin],&a[ki]);//key与a[begin]交换 使key总位于起始位置 
	//if(begin>=end) return;//子树为空或者只有一个结点,直接返回 
	while(begin<end)
	{
		if(a[end]>a[ki]) end--;//key对面的下标先动(一般以起点/终点为key) 找比key小的值 
		if(a[begin]<a[ki]) begin++;//找比key大的值 
		Swape(&a[end],&a[begin]);
	}
	Swape(&a[begin],&a[ki]);//此时key左边的值都比key小,右边都比key大 
	ImproveQuitSort(a,bi,ki-1);//遍历左子树 对key左边的值进行排序 
	ImproveQuitSort(a,ki+1,ei);//遍历右子树 对key右边的值进行排序
}

6.2快排(双指针法)

对于快排的实现,我们同样可以使用二个指针来解决。

1.取第一个元素为key,prve指向下标为0的元素,cur指向prve的前一个。

2.如果cur指向的值大于key cur就++,否则prve先++,再和cur交换,最后cur++。

3.当cur指向最后一个元素后面时,prve和key交换。

4.递归循环。

这个过程本质上就是不断的把大于key的值往后排,小于key的向前移。

(prve永远不会超过cur,因为无论cur大于还是小于key都会++)

//快排双指针法
void  PointerQuitSort(int *a,int begin,int end)
{
	if(begin>=end) return;
	int keyi=begin;//第一个元素为key 
	int prev=begin;//prve指向begin 
	int cur=prev+1;//cur在prve前面 
	while(cur<=end)//cur到最后一个元素后面结束 
	{
		if(a[cur]>a[keyi]) cur++;//如果cur指向的元素大于key就++ 小于key就停下 
		else Swape(&a[++prev],&a[cur++]);
		//否则prve先++ 再与cur指向元素交换 最后cur++ (先++是为了让prve指向大于key的值) 
	}
	Swape(&a[prev],&a[keyi]);//当cur越界时 prev指向的值仍是小于key的 可以直接与key交换 
	keyi=prev;
	PointerQuitSort(a,begin,keyi-1);
	PointerQuitSort(a,keyi+1,end);
}

6.3快排(非递归)

我们可以利用栈结构来模拟递归过程。

我们可以把函数参数也就是begin,end压入栈,当一对begin,end处理完,再压入它右左子树的begin,end直到栈为空。因为栈是先进后出,如果想先处理左子树就先压入右子树,再压入左子树。

(注意入栈 出栈顺序,不要把左右范围搞反)

(压入左右子树范围时 注意不要越界)

//快排非递归
void StackQuitSort(int *a,int begin,int end)
{
	ST q;
	StackInit(&q);
	StackPush(&q,end);//先压右边 
	StackPush(&q,begin);//再压左边 
	while(!StackEmpty(&q))
	{
		int left=StackTop(&q);//此时栈顶元素为begin 
		StackPop(&q);
		int right=StackTop(&q);
		StackPop(&q);
		if(left>=right) return;//用双指针进行一趟排序 
	    int keyi=left;
	    int prev=left;
	    int cur=prev+1;
	    while(cur<=right)
	   {
		    if(a[cur]>a[keyi]) cur++;
		    else Swape(&a[++prev],&a[cur++]); 
	   }
	    Swape(&a[prev],&a[keyi]);
	    keyi=prev;
	    if(keyi+1<=right)//防止keyi+1越界 先压右右子树  
	    {
	      StackPush(&q,right);
	      StackPush(&q,keyi+1);
	    }
	    if(keyi-1>=left)//再压左子树 (出栈时会先遍历左子树) 
	    {
	     StackPush(&q,keyi-1);
	     StackPush(&q,left);
	    }
	}
	StackDestroy(&q);
}

7.归并排序

归并排序递归实现过程就像二叉树的后续遍历。

1.从中间不断分左右子树 直到剩1个结点时返回。

2.然后归并左右子树 较小的值存入tmp中,完成后把tmp复制到a中。

3.一级一级向上返回。

//归并排序
void _MergeSort(int *a,int begin,int end,int* tmp)
{
	if(begin==end) return;//只有一个不用排 
	int mid=(begin+end)/2;
	int i=begin;//记录起始位置 
	int begin1=begin,end1=mid;//左子树范围 
	int begin2=mid+1,end2=end; //右子树范围 
	_MergeSort(a,begin1,end1,tmp);
	_MergeSort(a,begin2,end2,tmp);
	while(begin1<=end1&&begin2<=end2)//左右子树中选取最小值存入 
	{
		if(a[begin1]>a[begin2])
		{
			tmp[i++]=a[begin1];
			begin1++;
		}
		else
		{
            tmp[i++]=a[begin2];
			begin2++;		
		}
	}
	while(begin1<=end1) tmp[i++]=a[begin1++];//将剩余元素按顺序存入数组 
	while(begin2<=end2) tmp[i++]=a[begin2++];
	memcpy(a+begin,tmp+begin,(end - begin + 1)*4);//将tmp排好数据复制到a 最后一个参数是字节数
} 

void MergeSort(int *a,int n)
{
	int *tmp=(int*)malloc(sizeof(int)*n);//给新建数组分配空间 
	if(tmp==NULL)
	{
		perror("malloc fail");
		return ; 
	}
	_MergeSort(a,0,n-1,tmp);//防止反复申请空间 再建一个函数进行递归
	free(tmp);
	tmp=NULL;
	return;
} 

7.1归并非递归

递归变非递归我们可以利用栈,队列或者直接用while循环来解决。

归并非递归直接从叶子结点(gap==1)开始,两个两个进行个归并。(gap为一组中的元素个数)

最后一层叶子结点归并完,进入下一层接着归并。

以此循环 直到一组中的元素大于整个数组的元素个数(gap>n)

//归并排序(非递归)
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);//给新建数组分配空间 
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	int gap = 1;//gap为一组中要排序的个数(可以理解为子树中结点个数)
	int i,j;
	while (gap < n)//一组中的个数要小于等于n 两组两组就行归并
	{
		for (i = 0; i < n; i += 2*gap)//i为初始位置 因为两两进行归并 所以i+=2*gap
		{
			j = i;//j记录初始位置
			int begin1 = i, end1 = begin1 + gap - 1;//两组元素归并,第一组的左右范围
			int begin2 = end1 + 1, end2 = begin2 + gap - 1;//第二组的左右范围
			if (end1 >= n || begin2 >= n) break;//没有第二组元素 不用归并
			if (end2 >= n) end2 = n - 1;//第二组元素有一部分 归并 要防止越界
			while (begin1 <= end1 && begin2 <= end2)//两组元素进行归并
			{
				if (a[begin1] > a[begin2])
				{
					tmp[j++] = a[begin1];
					begin1++;
				}
				else
				{
					tmp[j++] = a[begin2];
					begin2++;
				}
			}
			while (begin1 <= end1) tmp[j++] = a[begin1++];
			while (begin2 <= end2) tmp[j++] = a[begin2++];
			memcpy(a + i, tmp + i, (end2-i + 1) * sizeof(int));//i初始位置 end2终止位置
		}
		gap *= 2;//进入下一层 两组元素归并成一个所以*2
	}
	//本质上就是从叶子结点开始不断归并
	free(tmp);
	tmp = NULL;
	return;
}

实现代码时要注意1.左右子树范围不能越界

2.利用tmp对两组元素进行归并时,要用 j 先记录起始位置 i 后续j++不断存入下一个

8.计数排序

计数排序是对一组范围集中的数据进行排序,按顺序统计数组中相同元素出现的次数,同一个元素出现几次就输出几次。

1.首先我们要开辟一组数组tmp来记录数组中相同元素出现的次数,开辟数组的大小就要根据原数组值的范围来定,我们求出原数组中的max min就可以得出范围。

2.然后我们通过遍历的方式来出原数组中相同元素出现的次数。

3.最后根据tmp数组中记录的次数,有几次就在原数组中存入几次。

//计数排序
void CountSort(int *a,int n)
{
	int i,j=0,min=a[0],max=a[0];
	for(i=0;i<n;i++)//找出最大最小值 
	{
		if(min>a[i]) min=a[i];
		if(max<a[i]) max=a[i];
	}
	int range=max-min+1;//范围 
	int*tmp=(int*)malloc(sizeof(int)*range);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
	memset(tmp,0,sizeof(int)*range);//初始化为0 
	for(i=0;i<n;i++)//记录不同数值出现几次 
	{
		tmp[a[i]-min]++;//因为不一定从0开始,所以要减去min 
	}
	for(i=0;i<range;i++)//同一个值出现几次就输出几次 
	{
		while(tmp[i])
		{
			a[j++]=i+min; 
			tmp[i]--;
		}
	}
} 

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

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

国产编辑器EverEdit - 两种删除空白行的方法

1 使用技巧&#xff1a;删除空白行 1.1 应用场景 用户在编辑文档时&#xff0c;可能会遇到很多空白行需要删除的情况&#xff0c;比如从网页上拷贝文字&#xff0c;可能就会存在大量的空白行要删除。 1.2 使用方法 1.2.1 方法1&#xff1a; 使用编辑主菜单 选择主菜单编辑 …

可以输入的下拉框(下拉框数据过大,页面卡死)

项目场景&#xff1a; 提示&#xff1a;这里简述项目相关背景&#xff1a; 在项目中&#xff0c;有些下拉框的数据过于庞大&#xff0c;这样页面有时候会卡死&#xff0c;在vue3中常用的组件库element-puls中有个组件可以避免 在项目中&#xff0c;有些需求要求下拉框选择的同…

基于Python的音乐播放器 毕业设计-附源码73733

摘 要 本项目基于Python开发了一款简单而功能强大的音乐播放器。通过该音乐播放器&#xff0c;用户可以轻松管理自己的音乐库&#xff0c;播放喜爱的音乐&#xff0c;并享受音乐带来的愉悦体验。 首先&#xff0c;我们使用Python语言结合相关库开发了这款音乐播放器。利用Tkin…

谷粒商城-高级篇完结-Sleuth+Zipkin 服务链路追踪

1、基本概念和整合 1.1、为什么用 微服务架构是一个分布式架构&#xff0c;它按业务划分服务单元&#xff0c;一个分布式系统往往有很多个服务单元。由于服务单元数量众多&#xff0c;业务的复杂性&#xff0c;如果出现了错误和异常&#xff0c;很难去定位 。主要体现在&#…

ollama+FastAPI部署后端大模型调用接口

ollamaFastAPI部署后端大模型调用接口 记录一下开源大模型的后端调用接口过程 一、ollama下载及运行 1. ollama安装 ollama是一个本地部署开源大模型的软件&#xff0c;可以运行llama、gemma、qwen等国内外开源大模型&#xff0c;也可以部署自己训练的大模型 ollama国内地…

pandas系列----DataFrame简介

DataFrame是Pandas库中最常用的数据结构之一&#xff0c;它是一个类似于二维数组或表格的数据结构。DataFrame由多个列组成&#xff0c;每个列可以是不同的数据类型&#xff08;如整数、浮点数、字符串等&#xff09;。每列都有一个列标签&#xff08;column label&#xff09;…

Unity【Colliders碰撞器】和【Rigibody刚体】的应用——小球反弹效果

目录 Collider 2D 定义&#xff1a; 类型&#xff1a; Rigidbody 2D 定义&#xff1a; 属性和行为&#xff1a; 运动控制&#xff1a; 碰撞检测&#xff1a; 结合使用 实用检测 延伸拓展 1、在Unity中优化Collider 2D和Rigidbody 2D的性能 2、Unity中Collider 2D…

Java实现UDP与TCP应用程序

三、Java实现UDP应用程序 3.1 InetAddress类 java.net.InteAddress类是用于描述IP地址和域名的一个Java类&#xff1b; 常用方法如下&#xff1a; public static InetAddress getByName(String host)&#xff1a;根据主机名获取InetAddress对象public String getHostName()…

信号处理-消除趋势项

matlab 版本 python 版本 import numpy as np import matplotlib.pyplot as plt from matplotlib import rcParams# 设置中文字体 rcParams[font.sans-serif] [SimHei] # 设置默认字体为黑体 rcParams[axes.unicode_minus] False # 解决负号显示问题def compute_time(n, f…

Linux 安装 meilisearch

前言 由于项目部分数据需要用到搜索引擎进行检索&#xff0c;但是服务器资源有限&#xff0c;安装elasticsearch过于笨重&#xff0c;不太符合现实情况&#xff0c;所以选择了meilisearch作为搜索引擎来使用&#xff0c;目前使用接近一年&#xff0c;运行良好。 安装 在/usr/…

【C++数据结构——查找】二叉排序树(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 1. 二叉排序树的基本概念 2. 二叉排序树节点结构体定义 3. 创建二叉排序树 4. 判断是否为二叉排序树 5. 递归查找关键字为 6 的结点并输出查找路径 6. 删除二叉排序树中的节点 测试说明 通关代码 测试结果 任务描述 本关任务&a…

TCP与DNS的报文分析

场景拓扑&#xff1a; 核心路由配置&#xff1a; 上&#xff08;DNS&#xff09;&#xff1a;10.1.1.1/24 下(WEB)&#xff1a;20.1.1.1/24 左&#xff08;client&#xff09;&#xff1a;192.168.0.1/24 右(PC3)&#xff1a;192.168.1.1/24Clint2配置&a…

OpenHarmony通过挂载镜像来修改镜像内容,RK3566鸿蒙开发板演示

在测试XTS时会遇到修改产品属性、SElinux权限、等一些内容&#xff0c;修改源码再编译很费时。今天为大家介绍一个便捷的方法&#xff0c;让OpenHarmony通过挂载镜像来修改镜像内容&#xff01;触觉智能Purple Pi OH鸿蒙开发板演示。搭载了瑞芯微RK3566四核处理器&#xff0c;树…

linux ansible部署

ansible部署完后&#xff0c;执行报错 # ansible one -i hosts -m ping dataos193 | FAILED! > {"msg": "Using a SSH password instead of a key is not possible because Host Key checking is enabled and sshpass does not support this. Please add …

【微服务】3、配置管理

微服务配置管理 已掌握的微服务组件及配置管理问题引出 已掌握注册中心、Openfan、远程调用、负载均衡、网关等组件&#xff0c;具备微服务开发能力&#xff0c;但仍存在其他问题待解决。微服务和网关存在大量配置文件&#xff0c;其中包含很多重复配置&#xff0c;如数据库、日…

C# 事件

目录 1、事件模型的5个组成部分2、使用内置委托类型声明事件2.1 EventHandler2.1.1 &#xff1f;2.1.2 this2.1.3 使用匿名函数和lamda表达式2.1.3.1 匿名函数2.1.3.2 lamda表达式 2.1.4 异常处理 2.2 EventHandler<TEventArgs> 3、使用自定义委托类型声明事件3.1 事件的…

php反序列化原生态 ctfshow练习 字符串逃逸

web262 拿着题审计一下 <?php error_reporting(0); class message{public $from;public $msg;public $to;public $tokenuser;public function __construct($f,$m,$t){$this->from $f;$this->msg $m;$this->to $t;} }$f $_GET[f]; $m $_GET[m]; $t $_GET[t…

【C语言程序设计——循环程序设计】利用循环求数值 x 的平方根(头歌实践教学平台习题)【合集】

目录&#x1f60b; 任务描述 相关知识 一、求平方根的迭代公式 1. 原理 2. 代码实现示例 二、绝对值函数fabs() 1. 函数介绍 2. 代码示例 三、循环语句 1. for循环 2. while循环 3. do - while循环 编程要求 测试说明 通关代码 测试结果 任务描述 本关任务&…

使用 Three.js 创建动态粒子效果

今天&#xff0c;带大家使用粒子实现一个粒子飞毯的效果&#xff0c;我们先来看一下效果。 实现 初始化场景 首先创建一个场景&#xff0c;所有 3D 对象都会被添加到这个场景中。 const scene new THREE.Scene();相机和渲染器 配置相机和渲染器来捕捉和显示场景。 相机…

20250103在Ubuntu20.04.5的Android Studio 2024.2.1.12中跑通Hello World

20250103在Ubuntu20.04.5的Android Studio 2024.2.1.12中跑通Hello World 2025/1/3 14:06 百度&#xff1a;android studio helloworld android studio hello world kotlin helloword kotlin 串口 no run configurations added android studio no run configurations added 1、…