【数据结构】——常见排序

news2024/11/27 3:51:40

文章目录

  • 一、 冒泡排序
  • 二、 选择排序
  • 三、插入排序
  • 四、 快速排序
    • 1. hoare版本
    • 2. 优化版本
    • 3. 前后指针法
    • 4. 非递归版本
  • 五、 堆排序
  • 六、 希尔排序
  • 七、 归并排序
    • 1. 递归版本
    • 2. 非递归版本
  • 八、 计数排序

在开始之前先准备一个交换数据的函数,排序会经常用到

//交换位置
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 flag = 0;
		for (int i = 1; i < n - j; i++)
		{
			if (a[i - 1] > a[i])
			{
				Swap(&a[i - 1], &a[i]);
				flag = 1;
			}
		}

		if (flag == 0)//判断是否全部排序完成
		{
			break;
		}
	}
}

二、 选择排序

在这里插入图片描述
如图所示,找到最小值,放在最前面,前面的N个数据默认为有序,就从N后继续开始排序
不过在下面的代码中我进行了改进,遍历一次找到最大和最小值放在两侧,提高效率

void SelectSort(int* a, int n)
{
	int begin = 0;
	int end = n - 1;
	while (begin < end)
	{
		int max = begin;
		int min = begin;
		for (int i = begin + 1; i <= end; i++)
		{

			if (max < a[i])
			{
				max = i;
			}
			if (min > a[i])
			{
				min = i;
			}
		}
		Swap(&a[begin], &a[min]);
		if (max == begin)
		{
			max = min;
		}
		Swap(&a[end], &a[max]);
		begin++;
		end--;
	}
}

为什么要加

if (max == begin)
		{
			max = min;
		}

在这里插入图片描述
就是怕遇到如上图这种情况

三、插入排序

在这里插入图片描述
数据从后向前进行对比,如果找到大于自己的就继续往前对比,找到小于的就插入进去

// 插入排序
void InsertSort(int* a, int n)
{
	for (int i = 0; i < n - 1; i++)
	{
		int end = i;
		int tmp = a[end + 1];
		while (end >= 0)
		{
			if (tmp < a[end])
			{
				a[end + 1] = a[end];
				end--;
			}
			else
			{
				break;
			}
		}
		a[end+1] = tmp;
	}

}

四、 快速排序

1. hoare版本

在这里插入图片描述

int PartSort1(int* a, int left, int right)
{
	//单趟
	if(left >= right)
		return;
	int keyi = left;
	int begin = left, end = right;
	while (begin < end)
	{
		// 右边找小
		while (begin < end && a[end] >= a[keyi])//begin < end防止越界
		{
			--end;
		}

		// 左边找大
		while (begin < end && a[begin] <= a[keyi])
		{
			++begin;
		}

		Swap(&a[begin], &a[end]);
	}

	Swap(&a[keyi], &a[begin]);//交换l与r相遇位置和key的位置
	keyi = begin;//方便分割区间
	PartSort1(a, left, keyi - 1);//左区间
	PartSort1(a, keyi + 1, right);//右区间
	return begin;
}

在这里插入图片描述

2. 优化版本

上面hoare的版本在数据有序的情况下,会尴尬很多,我们的key每次都是最小值或者最大值,递归的深度就会变成N。
所以为了避免这种情况发生,我们key需要是一个接近中位数的值。

两种方法

  1. 随机数选key
  2. 三数取中

那我这里就以三数取中为例:
left、right、mid,三个数进行对比,取大小在中间的那个值。

int GetMid(int* a,int left, int right)//三数取中
{
	int mid = (left + right) / 2;
	if (a[left] > a[mid])
	{
		if (a[mid] > a[right])//left最大,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;
	}

}



void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//小区间优化
	if ((right - left + 1) <= 10)
	{
		InsertSort(a+left, right - left + 1);
	}
	else
	{
		int mid = GetMid(a, left, right);//三数取中
		Swap(&a[left], &a[mid]);
		int key = left;
		int begin = left;
		int end = right;
		while (begin < end)
		{
			//走边找小
			if (begin < end && a[end] >= a[key])
			{
				end--;
			}
			//左边找大
			if (begin < end && a[begin] <= a[key])
			{
				begin++;
			}
			Swap(&a[end], &a[begin]);
		}
		Swap(&a[key], &a[begin]);//交换l与r相遇位置和key的位置
		key = begin;//方便分区间
		QuickSort(a, left, key - 1);//左区间
		QuickSort(a, key + 1, right);//右区间
	}
	
}

这里还没有结束,可以再优化一下,在我们进行快排的时候,如果每次的区间都能二分的化,这个递归的过程是可以看出一颗二叉树,而在满二叉树的叶子节点个数为整棵树的一半,对于快排来说它的最后一层和倒数第二层,是不用去排和只排一个数的,但是却还要开辟栈帧,所以我们这里使用小区间优化带代码如下直接使用当区间小于等于10时进行插入排序。

void QuickSort(int* a, int left, int right)
{
	if (left >= right)
		return;
	//小区间优化
	if ((right - left + 1) <= 10)
	{
		InsertSort(a+left, right - left + 1);//每次递归会有偏移,所以要加上偏移量left
	}
	else
	{
		//递归……
	}
}

3. 前后指针法

在这里插入图片描述
通过动图我们可以判断出,当cur找到小于key的值,prev++,当++prev != cur,就会进行交换,当cur越界时,再把key和prev进行交换

//快速排序前后指针法
int PartSort1(int* a, int left, int right)
{
	int mid = GetMid(a, left, right);//三数取中
	Swap(&a[left], &a[mid]);
	int key = left;
	int prve = left;
	int cur = prve + 1;
	while (cur <= right)
	{
		if (a[cur] < a[key] && ++prve != cur)
			Swap(&a[prve], &a[cur]);
		cur++;
	}
	Swap(&a[key], &a[prve]);
	return prve;
}

4. 非递归版本

快速排序其实跟二叉树的前序遍历非常相似,都是深度优先遍历。
快速排序非递归可以用栈实现,因为栈是后进先出所以要先把右区间的数压进栈
在这里插入图片描述

//快排非递归方法,用栈实现
#include "Stack.h"
void QuickSortNonR(int* a, int left, int right)
{
	Stack st;
	StackInit(&st);
	StackPush(&st, right);
	StackPush(&st, left);
	while (!StackEmpty(&st));
	{
		int begin = StackTop(&st);
		StackPop(&st);
		int end = StackTop(&st);
		StackPop(&st);
		int key = PartSort1(a, begin, end);//使用上面的前后指针法辅助单趟排序
		//[begin,key - 1] key [key + 1, end]
		if (key + 1 < end)
		{
			StackPush(&st, end);
			StackPush(&st, key + 1);
		}
		if (key - 1 > begin)
		{
			StackPush(&st,key - 1);
			StackPush(&st,begin);
		}
	}
	StackDestroy(&st);
}

五、 堆排序

我们建堆的时候,如果想要实现降序,那么我们应该建小堆,而不是大堆,因为如果我们建了大堆,只是堆成了降序,并不是原来的数组成了降序,升序相反建大堆。
在这里插入图片描述


void HeapSort(int* a, int max)//max为最大个数
{
	//建堆
	for (int i = 0; i <max; i++)
	{
		AdjustUp(a, i);//模拟插入建小堆
	}
	//排序
	int end = max - 1;//找到最后一个元素的下标进行交换
	while (end>0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, 0, end);
		--end;//最后的有序不再排序
	}
}

这里还可以再优化,降低时间复杂度

/*建堆方法一
	for (int i = 1; i < n; i++)
	{
		AdjustUp(a, i);
	}*/
	//建堆方法二
	for (int i = (n - 1 - 1) / 2; i >= 0; i--)//从第一个非叶子节点调整
	{
		AdjustDown(a, n, i);
	} 

	int end = n - 1;
	while (end > 0)
	{
		Swap(&a[0], &a[end]);
		AdjustDown(a, end, 0);
		--end;
	}
}

六、 希尔排序

第一步:预排序
第二步:插入排序

在这里插入图片描述

1.希尔排序是对直接插入排序的优化。
2.当gap > 1时都是预排序,目的是让数组更接近于有序。当gap == 1时,数组已经接近有序的了,这样就会很快。这样整体而言,可以达到优化的效果。我们实现后可以进行性能测试的对比。
以gap==3为例

// 希尔排序
void ShellSort(int* a, int n)
{
	/*int gap = 3;*/
	//第一种方法:一组一组gap走
	/*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;

		}
	}*/
	//第二种方法:一次性走完
	/*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;

	}*/

当gap等于1时,和插入排序一摸一样
在这里插入图片描述
为什么i<n-gap
在这里插入图片描述
如图所示,为了防止tmp越界

这里我们可以总结出,在预排序阶段
gap越大,大的可以越快跳到后面,小的可以越快跳到前面,但是越不接近有序
gap越小,跳的就越慢,但是更接近有序。

所以,还可以再优化一下

	//第三种方法:优化一下gap = gap / 3 + 1;
	int gap = n;
	while (gap > 1)
	{
		for (int i = 0; i < n - gap; ++i)
		{
			gap = gap / 3 + 1;
			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;

		}
	}
}

在这个方法中,当gap > 1时是预排序,gap == 1时是插入排序

七、 归并排序

归并排序的思想就是分治法(分而治之)

在这里插入图片描述

1. 递归版本

在这里插入图片描述
如果在原数组上进行比较交换,会导致数据被覆盖,所以我们开辟一个tmp数组,来存放交换结果,再返回给原数组
下面的代码就像是二叉树的后序遍历

void _MergeSort(int* a, int* tmp, int begin, int end)
{
	if (begin >= end)//返回条件,区间只剩一个值
		return;
	
	int mid = (begin + end) / 2;
	//左右区间必须这么分,不然会出问题
	_MergeSort(a, tmp, begin, mid);
	_MergeSort(a, tmp, mid + 1, end);
	int begin1 = begin;
	int end1 = mid;
	int begin2 = mid + 1;
	int 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++];
	}
	//需要把偏移量begin加上,每归并一次就拷贝一次回去
	memcpy(a+begin, tmp+begin, (end - begin + 1)*sizeof(int));
}
void MergeSort(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
	}
	_MergeSort(a, tmp, 0, n - 1);
	free(tmp);
	tmp = NULL;
}

2. 非递归版本

如果也要使用栈实现的话,就需要两个栈,一个模仿递推的过程,一个模仿回归,就太麻烦了,其实循环就可以实现
在这里插入图片描述
那如果一组4个数据和一组3个数据可以进行归并嘛?也是可以的,因为归并排序并没有要求每组的数据都要相同,只要是有序就可以一起归并。

void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail!");
	}
	int gap = 1;
	//gap为每组归并的数据个数
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)//i代表每组归并的起始位置
		{
			int begin1 = i;
			int end1 = i + gap - 1;
			int begin2 = i + gap;
			int end2 = i + 2 * gap - 1;
			printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);
			int j = i;
			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, (end2 - i + 1) * sizeof(int));
		}
		printf("\n");
		gap *= 2;
	
	}
	free(tmp);
	tmp = NULL;
}

我打印了一下数组区间,发现越界了
在这里插入图片描述
通过上图可以看出,越界可以分为两种情况

  1. begin2越界了,后面就没有进行的必要的
  2. end2越界了,调整end2的位置即可

if (begin2 > len - 1)//begin2已经越界,说明只有一组了没必要再排
{
	break;
}
if (end2 > len - 1)//end2越界了进行修正即可
{
	end2 = len - 1;
}
void MergeSortNonR(int* a, int n)
{
	int* tmp = (int*)malloc(sizeof(int) * n);
	if (tmp == NULL)
	{
		perror("malloc fail");
		return;
	}
 
	// gap每组归并数据的数据个数
	int gap = 1;
	while (gap < n)
	{
		for (int i = 0; i < n; i += 2 * gap)//i代表每组归并的起始位置
		{
			// [begin1, end1][begin2, end2]
			int begin1 = i, end1 = i + gap - 1;
			int begin2 = i + gap, end2 = i + 2 * gap - 1;
 
			//printf("[%d,%d][%d,%d] ", begin1, end1, begin2, end2);
 
			// 第二组都越界不存在,这一组就不需要归并
			if (begin2 >= n)
				break;
 
			// 第二的组begin2没越界,end2越界了,需要修正一下,继续归并
			if (end2 >= n)
				end2 = n - 1;
 
			int j = i;
			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));
		}
 
		//printf("\n");
 
		gap *= 2;
	}
 
	free(tmp);
	tmp = NULL;
}

八、 计数排序

在这里插入图片描述

第一步:统计每个值出现的次数
第二步:排序

在这里插入图片描述
那如果我的数据是{100, 104, 109, 109, 102},那count数组是不是就要开辟109个空间呢,那就太浪费空间了,所以我们要相对映射,按范围开空间,那么就用最大的值减最小的值。当我们要返回时,下标加最小的值就可以恢复了。

void CountSort(int* a, int n)
{
	int min = a[0];
	int max = a[0];//从第一个值开始对比找极大极小值
	for (int i = 1; i < n; i++)
	{
		if (a[i] < min)
			min = a[i];
		if (a[i] > max)
			max = a[i];
	}
	int range = max - min + 1;
	int* count = (int*)calloc(range,sizeof(int));//calloc可以将数组里的每一个值初始化为0

	//计数
	for (int i = 0; i < n; i++)
	{
		count[a[i] - min]++;
	}
	//排序
	int i = 0;
	for (int j = 0; j < range; j++)
	{
		while (count[j]--)
		{
			a[i++] = j + min;
		}
	}
	free(count);
	count = NULL;
}

希望这篇博客对你有帮助!!!

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

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

相关文章

【设计模式深度剖析】【8】【行为型】【备忘录模式】| 以后悔药为例加深理解

&#x1f448;️上一篇:观察者模式 设计模式-专栏&#x1f448;️ 文章目录 备忘录模式定义英文原话直译如何理解呢&#xff1f; 3个角色1. Memento&#xff08;备忘录&#xff09;2. Originator&#xff08;原发器&#xff09;3. Caretaker&#xff08;负责人&#xff09;类…

FPGA - 数 - 加减乘除

一&#xff0c;数的表示 首先&#xff0c;将二进制做如下解释&#xff1a; 2的0次方1 2的1次方2 2的2次方4 2的3次方8 ..... 以此类推&#xff0c;那么任何整数&#xff0c;或者说任意一个自然数均可以采用这种方式来表示。 例如&#xff0c;序列10101001&#xff0c;根据上述…

【数据挖掘】机器学习中相似性度量方法-欧式距离

写在前面&#xff1a; 首先感谢兄弟们的订阅&#xff0c;让我有创作的动力&#xff0c;在创作过程我会尽最大能力&#xff0c;保证作品的质量&#xff0c;如果有问题&#xff0c;可以私信我&#xff0c;让我们携手共进&#xff0c;共创辉煌。 路虽远&#xff0c;行则将至&#…

三运放仪表放大器通过设置单个电阻器的值来调整增益

从公式 1 中可以看出&#xff0c;我们可以通过调整单个电阻器 R G的值来调整仪表放大器的差分增益。这很重要&#xff0c;因为与电路中的其他电阻器不同&#xff0c; RG的值不需要与任何其他电阻器匹配。 例如&#xff0c;如果我们尝试通过更改 R 5的值来设置增益&#xff0c;…

PHP杂货铺家庭在线记账理财管理系统源码

家庭在线记帐理财系统&#xff0c;让你对自己的开支了如指掌&#xff0c;图形化界面操作更简单&#xff0c;非常适合家庭理财、记账&#xff0c;系统界面简洁优美&#xff0c;操作直观简单&#xff0c;非常容易上手。 安装说明&#xff1a; 1、上传到网站根目录 2、用phpMyad…

Linux文本处理三剑客+正则表达式

Linux文本处理常用的3个命令&#xff0c;脚本或者文本处理任务中会用到。这里做个整理。 三者的功能都是处理文本&#xff0c;但侧重点各不相同&#xff0c;grep更适合单纯的查找或匹配文本&#xff0c;sed更适合编辑匹配到的文本&#xff0c;awk更适合格式化文本&#xff0c;对…

牛客热题:兑换零钱(一)

&#x1f4df;作者主页&#xff1a;慢热的陕西人 &#x1f334;专栏链接&#xff1a;力扣刷题日记 &#x1f4e3;欢迎各位大佬&#x1f44d;点赞&#x1f525;关注&#x1f693;收藏&#xff0c;&#x1f349;留言 文章目录 牛客热题&#xff1a;兑换零钱(一)题目链接方法一&am…

学习资料分析

学习资料分析 速算运算 √截位直除分数比较等比修正其他速算方法基期与现期基本概念求基期求现期增长率与增长量增长相关统计术语求一般增长率比较一般增长率增长量比重比重相关公式求比重平均数倍数间隔增长乘积增长率年增长率混合增长率资料分析:主要测查报考者对文字、数字…

windows环境如何运行python/java后台服务器进程而不显示控制台窗口

1.通常我们在windows环境下使用Java或Python语言编写服务器程序&#xff0c;都希望他在后台运行&#xff0c;不要显示黑乎乎的控制台窗口&#xff1a; 2.有人写了一个bat文件: cd /d D:\lottery\server && python .\main.py 放到了开机自启动里&#xff0c;可是开机的…

“土猪拱白菜” 的学霸张锡峰,如今也苦于卷后端

大家好&#xff0c;我是程序员鱼皮&#xff0c;前几天在网上刷到了一个视频&#xff0c;是对几年前高考励志演讲的学霸张锡峰的采访。 不知道大家有没有看过他的演讲视频。在演讲中&#xff0c;衡水中学的学霸张锡峰表达了城乡孩子差距大、穷人家的孩子只想要努力成为父母的骄…

港理工最新综述:基于LLM的text-to-SQL调查(方法实验数据全面梳理)1

【摘要】文本到SQL旨在将自然语言问题转换为可执行的SQL语句,这对用户提问理解、数据库模式理解和SQL生成都是一个长期存在的挑战。传统的文本到SQL系统包括人工工程和深度神经网络。随后,预训练语言模型(PLMs)被开发并用于文本到SQL任务,取得了可喜的成绩。随着现代数据库变得…

02_01_SpringMVC初识

一、回顾MVC三层架构 1、什么是MVC三层 MVC是 模型&#xff08;Model&#xff09;、视图&#xff08;View&#xff09;、控制器&#xff08;Controller&#xff09;的简写&#xff0c;是一种软件设计规范。主要作用是降低视图与业务逻辑之间的双向耦合&#xff0c;它不是一种…

如何轻松利用人工智能深度学习,提升半导体制造过程中的良率预测?

背景 这个项目涉及半导体制造过程的监测领域。在半导体制造中&#xff0c;不断收集来自传感器或过程测量点的信号是常态。然而&#xff0c;并非所有这些信号在特定的监测系统中都同等重要。这些信号包括了有用的信息、无关的信息以及噪声。通常情况下&#xff0c;工程师获得的…

MySQL-----排序 GROUP BY

在我们对数据进行分析的时候&#xff0c;通常会根据一个或多个列对结果集进行分组&#xff0c;从而得到我们想要的结果。例如&#xff1a;统计考某一门课程的学生信息等。 而MySQL的GROUP BY 语句根据一个或多个列对结果集进行分组。同时&#xff0c;我们也可以使用 COUNT, SUM…

【实战进阶】用Zig高效引入外部库,打造专属命令行神器!

经过几周的密集练习&#xff0c;我们开始对 Zig 有了感觉了吧。我反正已经开始能熟练的安装 Zig 并搭建项目了。本篇将把这些核心的技能加以混合使用&#xff0c;拿编写命令行程序为目的&#xff0c;把整个流程给大家跑一遍&#xff0c;手把手教导一遍&#xff0c;和大家一起梳…

Vscode中使用make命令

前言 需要注意&#xff0c;如下操作需要进行网络代理&#xff0c;否则会出现安装失败的情况 安装 第一步 — 安装MingGW &#xff08;1&#xff09;进入官网下载 &#xff08;2&#xff09;下载完成之后&#xff0c;双击exe文件 &#xff08;3&#xff09;点击Install &#x…

day09--151.翻转字符串里的单词+ 右旋字符串

一、151.翻转字符串里的单词 题目链接&#xff1a;https://leetcode.cn/problems/reverse-words-in-a-string/ 文章讲解&#xff1a;https://programmercarl.com/0151.%E7%BF%BB%E8%BD%AC%E5%AD%97%E7%AC%A6%E4%B8%B2%E9%87%8C%E7%9A%84%E5%8D%95%E8%AF%8D.html#%E7%AE%97%E6%…

PROSAIL模型前向模拟与植被参数遥感

原文链接&#xff1a;PROSAIL模型前向模拟与植被参数遥感 “绿水青山就是金山银山”的生态文明理念现已深入人心&#xff0c;从顶层设计到全面部署&#xff0c;生态文明建设进入举措最实、推进最快、力度最大、成效最好的时期。生态文明评价必须将生态系统健康作为基本内容&am…

什么是深拷贝;深拷贝和浅拷贝有什么区别;深拷贝和浅拷贝有哪些方法(详解)

目录 一、为什么要区别深拷贝和浅拷贝 二、浅拷贝 2.1、什么是浅拷贝 2.2、浅拷贝的方法 使用Object.assign() 使用展开运算符(...) 使用数组的slice()方法&#xff08;仅适用于数组&#xff09; 2.3、关于赋值运算符&#xff08;&#xff09; 三、深拷贝 3.1、什么是…

全网首发:教你如何直接用4090玩转最新开源的stablediffusion3.0

1.stablediffusion的概述&#xff1a; Stable Diffusion&#xff08;简称SD&#xff09;近期的动态确实不多&#xff0c;但最新的发展无疑令人瞩目。StableCascade、Playground V2.5和Stableforge虽然带来了一些更新&#xff0c;但它们在SD3面前似乎略显黯然。就在昨晚&#x…