常用排序算法总结(直接插入排序、选择排序、冒泡排序、堆排序、快速排序、希尔排序、归并排序)

目录

一. 直接插入排序

二:选择排序

三:冒泡排序

四.堆排序

五:希尔排序

六:快速排序(递归与非递归)

七.归并排序(递归与非递归)


一. 直接插入排序

🌟排序思路

        直接插入排序的基本原理是将一条记录插入到已排好的有序表中,从而得到一个新的、记录数量增1的有序表,其思路就和我们摸扑克牌一样,每摸到一张牌按照大小把他插入到对应位置,这样等摸完全部的牌时,我们手里的牌就是有序的

动态图解:

💬特点

🚩时间复杂度:

        O(N^2)(若待排序表为有序的则时间复杂度为O(N))

🚩空间复杂度:

        空间复杂度为O(1)

🚩稳定性: 

        稳定

⚡代码演示: 

void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
        //首先保存一下待插入的元素
		int tmp = a[end + 1];
 
        //比较的最坏情况时end=0
		while (end >= 0)
		{
 
            //若待排序元素比a[end]小,则让a[end]向后移动腾位置
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
                //由于本来数组就为有序数组,当不满足上述条件时,说明找到了待插入的位置
				break;
			}
		}
        //插入数据
		a[end + 1] = tmp;
	}
}

二:选择排序

🌟排序思路

 每次选出数组的最小值和最大值,分别置于数组头尾处,缩小排序范围重复操作

动态图解:

💬特点

🚩时间复杂度:

        时间复杂度为:O(N^2)

🚩空间复杂度:

        空间复杂度为O(1)

🚩稳定性:

        不稳定

⚡代码演示: 

void SelectSort(int* a, int n)
{
	int begin = 0, end = n - 1;

	while (begin < end)
	{
		int mini = begin, maxi = begin;
		for (int i = begin + 1; i <= end; ++i)
		{
			if (a[i] < a[mini])
			{
				mini = i;
			}

			if (a[i] > a[maxi])
			{
				maxi = i;
			}
		}

		Swap(&a[begin], &a[mini]);
		if (maxi == begin)
		{
			maxi = mini;
		}
		Swap(&a[end], &a[maxi]);

		++begin;
		--end;
	}
}

三:冒泡排序

🌟排序思路

比较相邻元素的大小,将大的元素往后交换,每一轮比较能确定一个最大值的位置

动态图解:

💬特点

🚩时间复杂度:

        时间复杂度为:O(N^2)

🚩空间复杂度:

        空间复杂度为O(1)

🚩稳定性:

        稳定

 ⚡代码演示: 

/* 冒泡排序 */
void BubbleSort(int arr[], int length) 
{
	for (int i = 0; i < length; i++)
	{
		for (int j = 0; j < length -  i - 1; j++)
		{
			if (arr[j] > arr[j + 1])
			{
				int temp;
				temp = arr[j + 1];
				arr[j + 1] = arr[j];
				arr[j] = temp;
			}
		}
	}
}

四.堆排序

🌟排序思路

1.首先将待排序数组建为大堆,此时堆顶元素就为数组最大值了

2.交换堆顶和堆尾元素,此时最大元素就到了堆尾,目前数组最大元素就排好了,现在就假设堆里没有当前这个最大元素了,堆头下面的左右子树仍然是大堆,只需要再将堆顶元素向下调整到合适位置,剩下的n-1个元素还是大堆

3.堆头堆尾交换,向下调整,如此反复就可排序

ps.排序以升序为例,升序建大堆,降序建小堆      

💬特点

🚩时间复杂度:

       O(N*lgN)

🚩空间复杂度:

        O(1)

🚩稳定性:

        不稳定

⚡代码演示: 

#include<stdio.h>
typedef int HeapDataType;
 
void swap(HeapDataType* a, HeapDataType* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
//大堆
void AdjustUp(HeapDataType* a, int child)
{
	int parent = (child - 1) / 2;
	while (child>0)
	{
		if (a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			child = parent;
			parent = (parent - 1) / 2;
		}
		else
		{
			break;
		}
	}
}
//大堆
void AdjustDown(HeapDataType* a, int size, int parent)
{
	int child = parent * 2 + 1;
 
	while (child<size)
	{
		//找较大的孩子
		if (a[child + 1] > a[child] && child+1<size)
		{
			child = child + 1;
		}
 
		if (a[parent] < a[child])
		{
			swap(&a[parent], &a[child]);
			parent = child;
			child = parent * 2 + 1;
		}
		else
		{
			break;
		}
	}
}
 
void HeapSort(HeapDataType* a, int size)
{
	//建堆
	for (int i = 1; i < size; i++)
	{
		AdjustUp(a, i);
	}
	//排序:升序
	int end = size - 1;
	while (end>0)
	{
		swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);  //end指最后一个元素,同时end的值为前面元素的个数
		end--;
	}
}

 五:希尔排序

🌟排序思路

  1. 预排序:先将数组分组,将每个组排序,目的是让整个数组相对有序
  2. 插入排序:待数组相对有序后,进行直接插入排序,这样效率比较高

图解:

假设待排序数组为[9 8 7 6 5 4 3 2 1]

1.我们将他们每隔三个坐标分为一组,假设gap=3

2.对三个数组分别进行直接插入排序,使数组整体相对有序

3.对数组整体进行插入排序

 💬特点

🚩时间复杂度:

       O(N^1.3)

🚩空间复杂度:

        O(1)

🚩稳定性:

        不稳定

 ⚡代码演示: 

void ShellSort(int* a, int n)
{
    //首先将gap定为n
	int gap = n;
 
	/*while (gap > 1)
	{
		gap = gap / 3 + 1;
 
		for (int j = 0; j < gap; j++)
		{
			for (int i = j; i < n - gap; i += gap)
			{
				int end = i;
				int tmp = a[end + gap];
				while (end >= 0)
				{
					if (tmp < a[end])
					{
						a[end + gap] = a[end];
						end -= gap;
					}
					else
					{
						break;
					}
				}
				a[end + gap] = tmp;
			}
		}
 
	}*/
 
	while (gap > 1)
	{
		gap = gap / 3 + 1;
 
		for (int i = 0; i < n - gap; i++)
		{
			int end = i;
			int tmp = a[end + gap];
			while (end >= 0)
			{
				if (tmp < a[end])
				{
					a[end + gap] = a[end];
					end -= gap;
				}
				else
				{
					break;
				}
			}
			a[end + gap] = tmp;
		}
	}
}

六:快速排序(递归与非递归)

1.⚡hoare

🌟排序思路

        将数组第一个元素定位关键值,定义begin和end指针,先让end从后往前找到比关键值小的数,begin从前往后找比关键值大的数,然后交换两数,直到 begin==end,再让关键值和begin所指的元素交换,最后返回关键值所在位置,便于后续进行递归或非递归操作

动态图解:

⚡代码演示: 

void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
 
//hoare
int PartSort1(int* a, int begin, int end)
{
	int left = begin, right = end;
	int keyi = begin;
	while (left < right)
	{
		//右边找小
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
			
		//左边找大
		while (left < right && a[left] < a[keyi])
		{
			left++;
		}
		swap(&a[left], &a[right]);
	}
	swap(&a[left], &a[keyi]);
	return left;
}

 2.⚡挖坑法

🌟排序思路

         首先将关键值定为数组第一个元素,并将坑位定为begin,先让end从后往前找到比关键值小的数,将这个数放到坑位,并更新坑位,再让begin从前往后找比关键值大的数,将这个数放到坑位,并更新坑位,直到 begin==end,再让关键值和坑位的元素交换,最后返回关键值所在位置

动态图解:

⚡代码演示: 

//挖坑法
int PartSort2(int* a, int begin, int end)
{
	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);
 
	int key = a[begin];
	int hole = begin;
	while (begin < end)
	{
		//右边找小,填入坑内,更新坑位
		while (begin<end && a[end]>=key)
		{
			--end;
		}
		a[hole] = a[end];
		hole = end;
		//左边找大,填入坑内,更新坑位
		while (begin<end && a[begin]<=key)
		{
			++begin;
		}
		a[hole] = a[begin];
		hole = begin;
	}
	a[hole] = key;
	return hole;
}

 3.⚡双指针法

🌟排序思路

        将数组第一个元素定为关键值,定义两个指针prev和cur,先让prev指向数组的第一个元素,cur指向prev的下一个元素,cur的作用是找比关键值小的元素,若cur所指元素不小于关键值则cur++,直到cur所值元素小于关键值,此时,prev和cur之间的元素都是大于关键值的元素,若prev+1不是cur的话就可以让prev++所指元素与cur所指元素交换了,直到cur指向数组的最后一个元素

动态图解:


 

⚡代码演示:

//双指针法
int PartSort3(int* a, int begin, int end)
{
	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);
 
	int key = begin;
	int prev = begin;
	int cur = prev + 1;
	while (cur <= end)
	{
		if (a[cur] < a[key] && ++prev != cur)
		{
			swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	swap(&a[prev], &a[key]);
	return prev;
}

💬特点

🚩时间复杂度:

最好情况:O(n*lgn)

最坏情况:O(n^2)

🚩空间复杂度

O(lgn)

🚩稳定性

不稳定

 🚩快速排序递归实现

⛲小优化:

        上述三个方法都是快速排序的单趟排序,但是上述排序还有一个小缺陷,因为三个方法都是固定第一个元素为关键值的,如果数组为有序的,那么从后往前找小就要遍历整个数组,效率会很小,所以通常会再写一个找中间值的函数:在数组开头结尾和中间三个数中找出一个大小在中间的数,并让这个数和数组第一个数交换,这样就会减少上述情况的发生

int GetMid(int* a, int begin, int end)
{
	int mid = (begin + end) / 2;
	if (a[begin] > a[mid])
	{
		if (a[mid] > a[end])
			return mid;
		else if (a[end] > a[begin])
			return end;
		else
			return begin;
	}
	else
	{
		if (a[begin] > a[end])
			return begin;
		else if (a[end] > a[mid])
			return mid;
		else
			return end;
	}
}
 
 
void swap(int* a, int* b)
{
	int tmp = *a;
	*a = *b;
	*b = tmp;
}
 
//hoare
int PartSort1(int* a, int begin, int end)
{
	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);
 
	int left = begin, right = end;
	int keyi = begin;
	while (left < right)
	{
		//右边找小
		while (left < right && a[right] >= a[keyi])
		{
			right--;
		}
			
		//左边找大
		while (left < right && a[left] < a[keyi])
		{
			left++;
		}
		swap(&a[left], &a[right]);
	}
	swap(&a[left], &a[keyi]);
	return left;
}
 
//挖坑法
int PartSort2(int* a, int begin, int end)
{
	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);
 
	int key = a[begin];
	int hole = begin;
	while (begin < end)
	{
		//右边找小,填入坑内,更新坑位
		while (begin<end && a[end]>=key)
		{
			--end;
		}
		a[hole] = a[end];
		hole = end;
		//左边找大,填入坑内,更新坑位
		while (begin<end && a[begin]<=key)
		{
			++begin;
		}
		a[hole] = a[begin];
		hole = begin;
	}
	a[hole] = key;
	return hole;
}
//双指针法
int PartSort3(int* a, int begin, int end)
{
	int mid = GetMid(a, begin, end);
	swap(&a[begin], &a[mid]);
 
	int key = begin;
	int prev = begin;
	int cur = prev + 1;
	while (cur <= end)
	{
		if (a[cur] < a[key] && ++prev != cur)
		{
			swap(&a[prev], &a[cur]);
		}
		cur++;
	}
	swap(&a[prev], &a[key]);
	return prev;
}
void QuickSort(int* a, int begin,int end)
{
	if (begin >= end)
		return;
    
    //三种方法任选其一即可
	int keyi = PartSort3(a, begin, end);
	QuickSort(a, begin, keyi - 1);
	QuickSort(a, keyi + 1, end);
}

 🚩快速排序非递归实现

🌟实现思路:

1.创建一个栈,将数组的右边界下标和左边界下标依次入栈

2.循环弹出数组的左右边界下标,并对该区间进行单趟排序,确定关键值的下标,分为左右两个区间

3.若左区间元素个数大于一个,将左区间右边界下标和左边界下标依次入栈,右区间同理

4.重复操作步骤2 3直到栈为空

⚡代码演示: 

void QuickSortNonR(int* a, int begin, int end)
{
	ST s;
	STInit(&s);
	STPush(&s,end);
	STPush(&s,begin);
 
	while (!STEmpty(&s))
	{
		int left = STTop(&s);
		STPop(&s);
		int right = STTop(&s);
		STPop(&s);
 
		int key = PartSort1(a, left, right);
 
		if (left < key - 1)
		{
			STPush(&s, key - 1);
			STPush(&s, left);
		}
 
		if (right > key + 1)
		{
			STPush(&s, right);
			STPush(&s, key+1);
		}
	}
	STDestroy(&s);
}

 七.归并排序(递归与非递归)

一:⛲递归实现

🌟算法思路

归并排序是用分治思想,分治模式在每一层递归上有三个步骤:

分解(Divide): 将n个元素分成个含n/2个元素的子序列。
解决(Conquer):用合并排序法对两个子序列递归的排序。
合并(Combine):合并两个已排序的子序列已得到排序结果。
        该算法需要先将数组分解,直到每个子序列为一个元素,再将子序列两两合并排序,思路可以参考二叉树的后序递归

 💬特点

平均时间复杂度:O(nlogn)
最佳时间复杂度:O(n)
最差时间复杂度:O(nlogn)   
空间复杂度:O(n)

动图展示:

⚡代码演示: 

void _MergeSort(int* a, int begin, int end, int* tmp)
{
	if (begin >= end)
		return;
 
    //分解
	int mid = (begin + end) / 2;
	_MergeSort(a, begin, mid, tmp);
	_MergeSort(a, mid+1, end, tmp);
 
	// 归并
	int begin1 = begin, end1 = mid;
	int begin2 = mid + 1, end2 = end;
	int i = begin;
 
	while (begin1 <= end1 && begin2 <= end2)
	{
		if (a[begin1] < a[begin2])
		{
			tmp[i++] = a[begin1++];
		}
		else
		{
			tmp[i++] = a[begin2++];
		}
	}
 
	while(begin1 <= end1)
	{
		tmp[i++] = a[begin1++];
	}
 
	while (begin2 <= end2)
	{
		tmp[i++] = a[begin2++];
	}
    
	memcpy(a + begin, tmp + begin, sizeof(int) * (end - begin + 1));
}
 
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);
}

二:⛲非递归实现

🌟算法思路:

        归并排序的递归实现是先将数组分解,直到每个子序列只有一个元素,在将子序列两两归并,非递归的实现思路则没有了分解的过程,直接将数组元素一个与一个归并,在两个与两个归并,在四个与四个归并.......,直到最后两组归并,数组变为有序数组

⚡代码演示:

void MergeSortNonR(int* a, int begin, int end)
{
	int n = end - begin + 1;
	int* tmp = (int*)malloc(sizeof(int) * (n));
	if (tmp == NULL)
	{
		perror("malloc");
		return;
	}
 
	int gap = 1;
    //当gap小于n时两个组才都有元素,才需要归并
	while (gap < n)
	{
		int j = 0;
		for (size_t i = 0; i < n; i += 2 * gap)
		{
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * 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++];
				}
				else
				{
					tmp[j++] = a[begin2++];
				}
			}
 
			while (begin1 <= end1)
			{
				tmp[j++] = a[begin1++];
			}
 
			while (begin2 <= end2)
			{
				tmp[j++] = a[begin2++];
			}
            //归并完后拷贝给原数组
			memcpy(a + i, tmp + i, sizeof(int) * (end2 - i + 1));
		}
		gap *= 2;
	}
	free(tmp);
}

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

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

相关文章

PaddleNLP评论观点抽取和属性级情感分析

项目地址&#xff1a;PaddleNLP评论观点抽取和属性级情感分析 - 飞桨AI Studio星河社区 (baidu.com) 情感分析旨在对带有情感色彩的主观性文本进行分析、处理、归纳和推理&#xff0c;其广泛应用于消费决策、舆情分析、个性化推荐等领域&#xff0c;具有很高的商业价值。 依托…

mysql综合实验

USE dept_emp; CREATE TABLE dept (deptno INT(2) NOT NULL COMMENT 部门编号,dname VARCHAR (15) COMMENT 部门名称,loc VARCHAR (20) COMMENT 地理位置 );-- 添加主键 ALTER TABLE dept ADD PRIMARY KEY (deptno); INSERT INTO dept (deptno,dname,loc)VALUES (10,财务…

Windows 11 UEFI引导修复的方法有哪些?

若Windows 11 UEFI 引导加载程序损坏了&#xff0c;您的电脑将无法启动&#xff0c;那么Win11怎么修复UEFI引导&#xff1f;下面我们就来了解一下。 通过自动修复进行UEFI引导修复 1. 将可启动U盘连接到损坏的电脑&#xff0c;进入BIOS设置您的电脑从U盘启动电脑。然后&#x…

TypeScript语法总结

JavaScript 与 TypeScript 的区别 TypeScript 是 JavaScript 的超集&#xff0c;扩展了 JavaScript 的语法&#xff0c;因此现有的 JavaScript 代码可与 TypeScript 一起工作无需任何修改&#xff0c;TypeScript 通过类型注解提供编译时的静态类型检查。 TypeScript 可处理已…

【论文解读】LERF:语言嵌入的辐射场(ICCV 2023 Oral)

来源&#xff1a;投稿 作者&#xff1a;橡皮 编辑&#xff1a;学姐 论文链接&#xff1a;https://arxiv.org/abs/2303.09553 项目主页&#xff1a;https://lerf.io](https://lerf.io 图 1&#xff1a;语言嵌入辐射场 (LERF)。 LERF 将 CLIP 表示建立在密集、多尺度的 3D 场中。…

Unity导出Android项目踩坑记录

导出的时候需要注意以下地方的配置&#xff1a; 1、buildSetting-> 设置ExportProject 2、buildsetting ->playerSetting ->设置IL2CPP 3、设置ndk edit->preferences->external tools->ndk 如果unity的ndk版本和android项目里的ndk版本不一致会报错&…

跨平台开发:构建适配多设备的直播电商APP

如今&#xff0c;跨平台开发成为构建适配多设备的直播电商APP的关键之一。本文将深入探讨跨平台开发的优势、选择适当的技术栈以及解决多设备适配的挑战。 一、跨平台开发的优势 1.1节省开发成本 通过一套代码即可在iOS和Android等多个平台上运行&#xff0c;极大地提高了开…

docker安装 mysql 8.0.32

首先下载 mysql 其次如果虚拟机以前安过mysql 需要把mysql关闭 命令 永久关闭mysql 但是当前不生效 需要重启虚拟机 systemctl enable mysqld 如果不想重启虚拟机 可以执行 systemctl stop mysqld //指定版本 docker pull mysql:8.0.32 // 拉取最新的…

Docker-安装实践(mysql,redis集群,tomcat)

docker实践(提供几个安装案例&#xff09; 安装Tomcat # 拉取镜像,可以指定标签不指定默认为最新 docker pull tomcat docker run -itd -p 8080:8080 --name tomcat tomcat:latest #这样内部默认80端口&#xff0c;主机的映射端口会随机分配一个 docker run -itd -P tomcat…

mac-hadoop3.3.6 源码构建以及踩坑记录

1. 为什么需要构建源码 因为hadoop的可执行文件 是在专门的机器上编译的 其中native库 不一定能适用于每个机器 导致在启动hadoop过程中 出现烦人的警告 WARN util.NativeCodeLoader: Unable to load native-hadoop library for your platform… using builtin-java classes w…

分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测

分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测 目录 分类预测 | Matlab实现WOA(海象)-XGboost分类【24年新算法】基于海象优化算法(WOA)优化XGBoost的数据分类预测分类效果基本描述程序设计参考资料 分类效果 基本…

mariadb数据库从入门到精通

mariadb数据库的安装以及安全初始化 mariadb数据库的安装以及安全初始化 mariadb数据库的安装以及安全初始化一、实验前提二、mariadb数据库的安装三、mariadb数据库安全初始化3.1 设定数据库基本的安全初始化3.2关闭对外开放端口 系列文章目录一、查看数据库二、进入库并且查看…

什么是安全SCDN,有什么作用?

前两天有个站长被朋友推荐联系到了德迅云安全&#xff0c;想要对自己网站做一些安全防护&#xff0c;聊天中问及到了安全SCDN是什么意思&#xff0c;有哪些作用&#xff1f;那么德迅云安全今天就来简单讲述一下安全SCDN&#xff0c;来了解下什么是安全SCDN&#xff0c;以及它有…

Pycharm无法刷新远程解释器的框架: Can‘t get remote credentials for deployment server

在Pycharm上部署项目到远程服务器&#xff0c;有时候需要启动SSH会话&#xff0c;启动的时候发现没反应&#xff0c;且事件日志显示&#xff1a;无法刷新远程解释器的框架: Can’t get remote credentials for deployment server 观察pycharm界面最下边&#xff0c;发现“无默…

vector的模拟实现

一、vector的基本结构 template<class T> class vector { public:typedef T* iterator;typedef const T* const_iterator; private:iterator _start;//vector的迭代器&#xff0c;指向起始位置iterator _finish;//指向存放最后一个元素的下一个位置iterator _end_of_sto…

C++类与对象(四):再谈构造函数(详解初始化列表)、Static成员

上次把默认的成员函数部分梳理完毕了&#xff1a;C初阶类与对象&#xff08;三&#xff09;&#xff1a;详解复制构造函数和运算符重载 今天接着讲下面的内容&#xff1a; 文章目录 1.再谈构造函数1.1构造函数体赋值1.2初始化列表1.2.1格式和概念1.2.2由来情况1情况2 1.2.3特性…

C语言第三弹---数据类型和变量

✨个人主页&#xff1a; 熬夜学编程的小林 &#x1f497;系列专栏&#xff1a; 【C语言详解】 【数据结构详解】 数据类型和变量 1、数据类型介绍1.1、整型1.2、浮点型1.3、字符型1.4、布尔类型1.5、各种数据类型的长度1.5.1、sizeof操作符1.5.2、数据类型的长度1.5.3、sizeo…

全网最详细!!Python 爬虫快速入门

1. 背景 最近在工作中有需要使用到爬虫的地方&#xff0c;需要根据 Gitlab Python 实现一套定时爬取数据的工具&#xff0c;所以借此机会&#xff0c;针对 Python 爬虫方面的知识进行了学习&#xff0c;也算 Python 爬虫入门了。 需要了解的知识点&#xff1a; Python 基础语…

【蓝桥杯EDA设计与开发】立创开源社区分享的关于蓝桥被EDA真题与仿真题的项目分析

立创开源社区内有几个项目分享了往年 EDA 设计题目与仿真题&#xff0c;对此展开了学习。 【本人非科班出身&#xff0c;以下对项目的学习仅在我的眼界范围内发表意见&#xff0c;如有错误&#xff0c;请指正。】 项目一 来源&#xff1a;第十四届蓝桥杯EDA赛模拟题一 - 嘉立…

JS-WebAPIs-其他事件(三)

• 页面加载事件 页面加载事件主要有二种事件&#xff0c;分别是load和DOMContentLoaded 加载外部资源&#xff08;如图片、外联CSS和JavaScript等&#xff09;加载完毕时触发的事件为什么要学&#xff1f; 有些时候需要等页面资源全部处理完了做一些事情老代码喜欢把 scrip…