无头单链表,有完整测试程序

news2024/12/22 20:05:08

🍟无头单链表

👻无头单链表的所有结点都存储有效信息
👻无头单链表相对带头单链表,在有些涉及更改头节点的函数上需要传二级指针

🍟头文件list.h

#define _CRT_SECURE_NO_WARNINGS
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLTDataType;
typedef struct SLTNode {
	SLTDataType data;
	struct SLTNode* next;
}SLTNode;

void SLTPrint(SLTNode* phead);
SLTNode* BuySLTNode(SLTDataType x);
void Destroy_Method1(SLTNode** pphead);
void Destroy_Method2(SLTNode** pphead);

//查
SLTNode* FindBySerialNumber(SLTNode* phead, int n);
SLTNode* FindByContent(SLTNode* phead, SLTDataType x);
//改
void ModefyNodeBySerialNumber(SLTNode* phead, int n, SLTDataType x);
void ModifyNodeByContent(SLTNode* phead, SLTDataType x1, SLTDataType x2);
//增
void PushFront(SLTNode** pphead, SLTDataType x);
void PushBack(SLTNode** pphead, SLTDataType x);

void InsertFrontBySerialNumber(SLTNode** pphead, int n, SLTDataType x);
void InsertFrontByAddress(SLTNode** pphead, SLTNode* pos, SLTDataType x);
void InsertFrontByContent(SLTNode** pphead, SLTDataType x1, SLTDataType x2);

void InsertBackBySerialNumber(SLTNode** pphead, int n, SLTDataType x);
void InsertBackByAddress(SLTNode* pos, SLTDataType x);
void InsertBackByContent(SLTNode* pphead, SLTDataType x1, SLTDataType x2);
//删
void PopFront(SLTNode** pphead);
void PopBack(SLTNode** pphead);

void DeleteFrontNode(SLTNode** pphead, SLTNode* pos);
void DeleteNode(SLTNode** pphead, SLTNode* pos);
void DeleteAfterNode(SLTNode* pos);

//测试
SLTNode* testPush_Front_Back();
void testInsertFront();
void testInsertBack();
void testPop();

🍟函数实现list.c

🥤 辅助操作函数

🍕打印链表函数

//辅助操作(打印链表,动态申请节点)
//打印链表
void SLTPrint(SLTNode* phead) {
	SLTNode* cur = phead;
	while (cur) {//当指针不为空时进入循环
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

🥤 创建节点,销毁链表函数

🍕创建节点函数

//2.动态申请一个节点
SLTNode* BuySLTNode(SLTDataType x) {
	//1.用malloc动态申请一个结点的空间
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	//2.判断是否申请成功,申请失败直接退出程序
	if (newnode == NULL) {
		perror("mallocfail");
		exit(-1);
	}
	//3.给结点的数据域赋值为x,给指针域赋值为NULL
	newnode->data = x;
	newnode->next = NULL;
	//4.返回节点的地址
	return newnode;
}

🍕销毁链表函数

🥓法1:先保留头节点,把后面的删完,最后删头结点

//销毁链表
//法1:先保留头节点,把后面的删完,最后删头结点
void Destroy_Method1(SLTNode** pphead) {
	//链表为空,无需删除
	assert(pphead);
	//先删后面,最后删头
	while ((*pphead)->next) {
		SLTNode* next = (*pphead)->next;
		(*pphead)->next = next->next;
		free(next);
	}
	free(*pphead);
}

🥓法2:从头往后删,头节点的值一直更新

//法2:从头往后删,头节点的值一直更新
void Destroy_Method2(SLTNode** pphead) {
	assert(pphead);
	SLTNode* cur = *pphead;
	while (cur) {
		SLTNode* next = cur->next;
		free(cur);
		cur = next;
	}
	*pphead = NULL;
}

🥤增删查改——查

🍕1.根据序号查找节点

序号:serial number

// 3.1根据序号查找节点
SLTNode* FindBySerialNumber(SLTNode* phead, int n) {
	SLTNode* cur = phead;
	for (int i = 1;i < n;i++) {
		cur = cur->next;
		//如果被查找结点不存在(超过链表范围),返回空指针
		if (cur == NULL) {
			return NULL;
		}
	}
	return cur;
}

🍕2.根据内容查找结点

//3.2根据内容查找结点
SLTNode* FindByContent(SLTNode* phead, SLTDataType x) {
	SLTNode* cur = phead;
	while (cur) {
		if (cur->data == x) {
			return cur;
		}
		cur = cur->next;
	}
	//查找不到返回空指针
	return NULL;
}

🥤增删查改——改

🍕1.改变节点内数据(通过序号找到被改节点)

//4.1改变节点内数据(通过序号找到被改节点) 
void ModefyNodeBySerialNumber(SLTNode* phead, int n, SLTDataType x) {
	SLTNode* cur = FindBySerialNumber(phead, n);
	cur->data = x;
}

🍕2.改变节点内数据(通过内容找到被改节点)

//4.2改变节点内数据(通过内容找到被改节点)
void ModifyNodeByContent(SLTNode* phead, SLTDataType x1, SLTDataType x2) {
	SLTNode* cur = FindByContent(phead, x1);
	cur->data = x2;
}

🥤增删查改——增

(头插,尾插,在指定节点前插,在指定节点后插)

🍕1.头插

//5.1头插
void PushFront(SLTNode** pphead, SLTDataType x) {
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}

👻问:为什么数据x传参时不传指针,而头结点要传二级指针?
👻因为数据x传进来就立马通过BuySLTNode函数被放到在堆区上申请的空间中了,就算不传指针出函数作用域也不会被销毁;而头结点要从原来的链表首结点变成新结点newnode,相当于头结点pphead的值发生变化了,头结点是一个一级指针,对一级指针的修改需要二级指针

🍕2.尾插

//5.2尾插
void PushBack(SLTNode** pphead, SLTDataType x) {
	SLTNode* newnode = BuySLTNode(x);
	if (*pphead == NULL) {
		*pphead = newnode;
		//改变结构体指针,要用二级指针,一级指针只能改形参,出作用域后形参被销毁
	}
	else {
		SLTNode* tail = *pphead;
		while (tail->next != NULL) {
			tail = tail->next;
		}
		tail->next = newnode;
	}
}

🍕3.在指定结点前插入

在指定结点前插入,需要得到指定位置的前置节点。有控制循环法和前置指针法让指针停留至前置节点处,但控制循环法只能在已知插入第几个节点时用,而前置指针法可以在任何情况下用

🥓3.1通过序号指定节点

👻用到了控制for循环法

//5.3在指定结点前插入(通过序号指定节点) 
void InsertFrontBySerialNumber(SLTNode** pphead, int n, SLTDataType x) {
	//产生新结点并赋值
	SLTNode* newnode = BuySLTNode(x);
	SLTNode* ptmp = *pphead;
	//如果要在第一个结点前插入结点,就成了头插
	if (n == 1) {
		PushFront(pphead, x);
		return;
	}
	//将结点放入指定位置的前一个结点,指定位置不包括第一个结点
	for (int i = 2;i < n;i++) {
		ptmp = ptmp->next;
		if (ptmp == NULL)
			printf("位置不合法");
	}
	newnode->next = ptmp->next;
	ptmp->next = newnode;

}

这个函数之所以要传二级指针是因为有头插的情况,需要调用SLTPushFront函数,但其实用一级指针,调用PushFront函数时再取一级指针的地址也行

🥓3.2内容->地址->找到结点

👻用到了while循环加前置指针法

//5.4在指定结点前插入(内容->地址->找到结点) 
//参数二pos是由test.c调用的Find函数返回的节点位置
void InsertFrontByAddress(SLTNode** pphead, SLTNode* pos, SLTDataType x) {
	assert(pphead);
	assert(pos);
	//头插情况
	if (*pphead == pos) {
		PushFront(pphead, x);
	}
	//非头插
	else {
		SLTNode* prev = *pphead;
		while (prev->next != pos) {
			prev = prev->next;
		}
		SLTNode* newnode = BuySLTNode(x);
		newnode->next = pos;
		prev->next = newnode;
		//由于有两个指针分别控制被插入结点和前一个结点,因此这两句顺序随意
	}
}

🥓3.3通过内容指定节点

👻用到了while循环加前置指针法

//5.5在指定结点前插入(通过内容指定节点)

void InsertFrontByContent(SLTNode** pphead, SLTDataType x1, SLTDataType x2) {
	SLTNode* cur = *pphead;
	//头插情况
	if (cur->data == x1) {
		PushFront(pphead, x2);
	}
	//非头插情况
	else {
		cur = FindByContent(*pphead, x1);
		SLTNode* prev = *pphead;
		while (prev->next != cur) {
			prev = prev->next;
		}//此时必须要第二个指针prev
		SLTNode* newnode = BuySLTNode(x2);
		newnode->next = cur;
		prev->next = newnode;
	}
}

当不借助FindByContent函数,只知道指定节点的内容时,需要进入每一个节点对比数据是否一致,这时只能用while训话加前置指针法,因为提前不知道指定位置,无法用通过控制for循环找到指定位置的前置节点

🍕4.在指定结点后插入

🥓4.1通过序号指定节点

//5.6 在指定结点后插入(通过序号指定节点)
void InsertBackBySerialNumber(SLTNode** pphead, int n, SLTDataType x) {
	//原链表为空
	if (*pphead == NULL) {
		SLTNode* newnode = BuySLTNode(x);
		*pphead = newnode;
	}
	//原链表不为空
	SLTNode* newnode = BuySLTNode(x);
	SLTNode* ptmp = *pphead;
	//将结点放入指定位置的后一个结点
	for (int i = 1;i < n;i++) {
		ptmp = ptmp->next;
		//指定节点超过最大长度,报错
		if (ptmp == NULL);
		assert(ptmp);
	}
	newnode->next = ptmp->next;
	ptmp->next = newnode;
}

🥓4.2内容->地址->找到节点

//5.7在指定结点后插入(内容->地址->找到节点)
//参数一pos是由test.c调用的SLTFind函数返回的节点位置
void InsertBackByAddress(SLTNode* pos, SLTDataType x) {
	assert(pos);
	SLTNode* newnode = BuySLTNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}

🥓4.3通过内容指定节点

不借助FindByContent函数

//5.8在指定结点后插入(通过内容指定节点)不借助FindByContent函数
void InsertBackByContent(SLTNode** pphead, SLTDataType x1, SLTDataType x2) {
	SLTNode* newnode = BuySLTNode(x2);
	SLTNode* cur = *pphead;
	//原链表为空,newnode就是头节点
	if (cur == NULL) {
		*pphead = newnode;
	}
	while (cur) {
		if (cur->data == x1) {
			//指定结点是尾结点
			if (cur->next == NULL) {
				cur->next = newnode;
			}
			//指定结点不是尾结点
			else {
				newnode->next = cur->next;
				cur->next = newnode;
			}
		}
		cur = cur->next;
	}
	//没找到
	return;
}

🥤增删查改——删

(头删,尾删,删除指定位置,删除指定位置的前一个节点,删除指定位置的后一个节点)

🍕1.头删

//6.1头删
void PopFront(SLTNode** pphead) {
	//头结点为空,报错
	assert(*pphead);
	//不为空
	SLTNode* newhead = (*pphead)->next;
	free(*pphead);
	*pphead = newhead;
}

🍕2.尾删

//6.2尾删
void PopBack(SLTNode** pphead) {
	//头结点为空,报错
	assert(*pphead);
	//只有一个结点
	if ((*pphead)->next == NULL) {
		free(*pphead);
		*pphead = NULL;
	}
	//有两个及以上个结点
	else {
		SLTNode* tail = *pphead;
		while (tail->next->next)
		{
			tail = tail->next;//指向尾节点的前置节点
		}
		free(tail->next);
		tail->next = NULL;
	}
}

🍕3.删除指定节点的前一个节点

(由于前置指针法相对于控制for循环法更普适,这里只展示前置指针法)

//删除指定节点的前一个节点
void DeleteFrontNode(SLTNode** pphead, SLTNode* pos) {
	//指定位置不可以是头节点
	if (pos == *pphead) {
		return;
	}
	//指定位置为第二个节点,头结点被删除,更新头结点
	if ((*pphead)->next == pos) {
		PopFront(pphead);
	}
	//定义pos的前置指针prev
	else {
		SLTNode* prevprev = *pphead;
		while (prevprev->next->next != pos) {
			prevprev = prevprev->next;
		}
		free(prevprev->next);
		prevprev->next = pos;
	}
}

🍕4.删除指定位置节点

//删除指定位置节点
void DeleteNode(SLTNode** pphead, SLTNode* pos) {
	//如果删除了头结点,头删函数
	if (pos == *pphead) {
		PopFront(pphead);
	}
	else {
		SLTNode* prev = *pphead;
		while (prev->next != pos) {
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
		pos = NULL;
	}
}

🍕5.删除指定节点的后一个节点

//删除指定节点的后一个节点
void DeleteAfterNode(SLTNode* pos) {
	//检查pos是否为空
	assert(pos);
	//检查pos是否是尾节点
	assert(pos->next);
	SLTNode* posNext = pos->next;
	pos->next = posNext->next;
	free(posNext);
	posNext = NULL;
}

🍟测试函数test.c

🥤测试头插尾插

SLTNode* testPush_Front_Back() {
	//测试头插PushFront
	printf("请输入头插长度:");
	int n = 0;
	scanf("%d", &n);
	printf("请依次输入结点的值:\n");
	SLTNode* plist = NULL;
	for (int i = 0;i < n;i++) {
		int val = 0;
		scanf("%d", &val);
		PushFront(&plist, val);
	}
	SLTPrint(plist);
	//测试尾插
	printf("请输入尾插长度:");
	int m = 0;
	scanf("%d", &m);
	printf("请依次输入结点的值:\n");
	for (int i = 0;i < m;i++) {
		int val = 0;
		scanf("%d", &val);
		PushBack(&plist, val);
	}
	SLTPrint(plist);
	return plist;
//销毁链表
	Destroy_Method1(&plist);
	//Destroy_Method2(&plist);
}

🥤测试在指定节点前插入

void testInsertFront() {
	SLTNode* plist = testPush_Front_Back();
	//在指定结点前插入(通过序号指定节点)
	printf("在指定结点前插入(通过序号指定节点)\n");
	printf("请输入结点编号:");
	int input1 = 0;
	scanf("%d", &input1);
	printf("请输入插入的数据");
	SLTDataType data1 = 0;
	scanf("%d", &data1);
	InsertFrontBySerialNumber(&plist, input1, data1);
	SLTPrint(plist);

	//在指定结点前插入(内容->地址->找到结点)
	printf("在指定结点前插入(内容->地址->找到结点)\n");
	printf("请输入要插入位置的数据:");
	SLTDataType data2 = 0;
	scanf("%d", &data2);
	SLTNode* pos = FindByContent(plist, data2);
	printf("请输入插入的数据:");
	SLTDataType data3 = 0;
	scanf("%d", &data3);
	InsertFrontByAddress(&plist, pos, data3);
	SLTPrint(plist);

	//在指定结点前插入(通过内容指定节点)
	printf("在指定结点前插入(通过内容指定节点)\n");
	printf("请输入要插入位置的数据:");
	SLTDataType data4 = 0;
	scanf("%d", &data4);
	printf("请输入插入的数据:");
	SLTDataType data5 = 0;
	scanf("%d", &data5);
	InsertFrontByContent(&plist, data4, data5);
	SLTPrint(plist);
	//销毁链表
	Destroy_Method1(&plist);
	//Destroy_Method2(&plist);
}

🥤测试在指定节点后插入

void testInsertBack() {
	SLTNode* plist = testPush_Front_Back();
	//在指定结点后插入(通过序号指定节点)
	printf("在指定结点后插入(通过序号指定节点)\n");
	printf("请输入节点编号:");
	int input2 = 0;
	scanf("%d", &input2);
	printf("请输入插入的数据:");
	SLTDataType data6 = 0;
	scanf("%d", &data6);
	InsertBackBySerialNumber(&plist, input2, data6);
	SLTPrint(plist);

	//在指定结点后插入(内容->地址->找到结点)
	printf("在指定结点后插入(内容->地址->找到结点)\n");
	printf("请输入要插入位置的数据:");
	SLTDataType data7 = 0;
	scanf("%d", &data7);
	SLTNode* pos = FindByContent(plist, data7);
	printf("请输入插入的数据:");
	SLTDataType data8 = 0;
	scanf("%d", &data8);
	InsertBackByAddress(pos, data8);
	SLTPrint(plist);

	//在指定结点后插入(通过内容指定节点)
	printf("在指定结点后插入(通过内容指定节点)\n");
	printf("请输入要插入位置的数据:");
	SLTDataType data9 = 0;
	scanf("%d", &data9);
	printf("请输入插入的数据:");
	SLTDataType data10 = 0;
	scanf("%d", &data10);
	InsertBackByContent(&plist, data9, data10);
	SLTPrint(plist);
	//销毁链表
	Destroy_Method1(&plist);
	//Destroy_Method2(&plist);
}

🥤测试各种删除

void testPop() {
	SLTNode* plist = testPush_Front_Back();
	//测试头删
	printf("测试头删\n");
	PopFront(&plist);
	SLTPrint(plist);

	//测试尾删
	printf("测试尾删\n");
	PopBack(&plist);
	SLTPrint(plist);

	//删除指定节点的前一个节点
	printf("删除指定节点的前一个节点\n");
	printf("请输入指定节点内容:\n");
	SLTDataType data11 = 0;
	scanf("%d", &data11);
	SLTNode* pos1 = FindByContent(plist, data11);
	DeleteFrontNode(&plist, pos1);
	SLTPrint(plist);

	//删除指定位置节点
	printf("删除指定位置节点\n");
	printf("请输入指定节点内容:\n");
	SLTDataType data12 = 0;
	scanf("%d", &data12);
	SLTNode* pos2 = FindByContent(plist, data12);
	DeleteNode(&plist, pos2);
	SLTPrint(plist);

	//删除指定节点的后一个节点
	printf("删除指定节点的后一个节点\n");
	printf("请输入指定节点内容:\n");
	SLTDataType data13 = 0;
	scanf("%d", &data13);
	SLTNode* pos3 = FindByContent(plist, data13);
	DeleteAfterNode(pos3);
	SLTPrint(plist);

	//销毁链表
	Destroy_Method1(&plist);
	//Destroy_Method2(&plist);

}

🥤主函数

测一个的时候其他三个注释掉,要不然会累死的O(∩_∩)O哈哈~😂

int main() {
	testPush_Front_Back();
	testInsertFront();
	testInsertBack();
	testPop();
}

🍟测试结果

🥤测试一:头插尾插

在这里插入图片描述

🥤测试二:在指定节点前插入节点

在这里插入图片描述

🥤测试三:在指定节点后插入节点

在这里插入图片描述

🥤测试四:各种删除

在这里插入图片描述
👻当前是有点小缺陷的,当通过指定内容找到节点时,如果遇到有多个相同数据的情况,会在第一个出现该数据的位置停下进行插入等操作,这是由于当前节点中的数据只是一个简单的数字,当以后节点内数据更多或每个节点都有自己的唯一标识时,就不会有这个缺陷了。

🌈把以上所有代码块连起来就是完整程序啦,最开始是头文件list.h,接下来是函数实现list.c,最后是测试文件test.c,其中分了4个函数。

🌈在插入和删除那块函数有点多,我把想到的全写上了,有点繁琐,大家主要借鉴思路哈🤣😂,如有错误请及时指正,感谢❤️

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

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

相关文章

不能乱点链接之获取cookie

这里是浏览器存储的某个网址的cookie 然后点击了链接就把参数获取到 因为document.cookie 会直接获取到浏览器cookie 所以为了拦截 存cookie的时候要设置&#xff1a; 设置httpOnly 只要http协议能够读取和携带 再document.cookie 就为空了 原文链接&#xff1a; 尚硅谷课程…

后端整理(MySql)

1 事务 1.1 事务ACID原则 原子性&#xff08;Atomicity&#xff09; 事务的原子性指的是事务的操作&#xff0c;要么全部成功&#xff0c;要么全部失败回滚 一致性&#xff08;Consistency&#xff09; 事务的一致性是指事务必须使数据库从一个一致状态转变成另一个一致性…

SolidUI社区-从开源社区角度思考苹果下架多款ChatGPT应用

文章目录 背景下架背景下架原因趋势SolidUI社区的未来规划结语如果成为贡献者 背景 随着文本生成图像的语言模型兴起&#xff0c;SolidUI想帮人们快速构建可视化工具&#xff0c;可视化内容包括2D,3D,3D场景&#xff0c;从而快速构三维数据演示场景。SolidUI 是一个创新的项目…

Typescript中的元组与数组的区别

Typescript中的元组与数组的区别 元组可以应用在经纬度这样明确固定长度和类型的场景下 //元组和数组类似&#xff0c;但是类型注解时会不一样//元组赋值的类型、位置、个数需要和定义的类型、位置、个数完全一致&#xff0c;不然会报错。 // 数组 某个位置的值可以是注解中的…

小白到运维工程师自学之路 第六十五集 (docker-compose)

一、概述 Docker Compose 的前身是 Fig&#xff0c;它是一个定义及运行多个 Docker 容器的工具。可以使用YAML文件来配置应用程序的服务。然后&#xff0c;使用单个命令&#xff0c;您可以创建并启动配置中的所有服务。Docker Compose 会通过解析容器间的依赖关系&#xff08;…

纷享销客携30+企业家朋友走进国产燃气轮机领军企业——新奥动力

7月26日下午&#xff0c;【数字中国-高效增长】名城优企游学系列活动之走进新奥动力成功举办&#xff01;新奥动力是国产燃气轮机领军企业&#xff0c;成立于2013年&#xff0c;致力于成为国际领先的微、小型燃气轮机制造商&#xff0c;其多项技术、产品填补国内空白。2022年新…

算法通关村—迭代实现二叉树的前序,中序,后序遍历

1. 前序中序后序递归写法 前序 public void preorder(TreeNode root, List<Integer> res) {if (root null) {return;}res.add(root.val);preorder(root.left, res);preorder(root.right, res);}后序 public static void postOrderRecur(TreeNode head) {if (head nu…

基于Web智慧森林防火GIS监测预警可视化系统

森林火灾是森林最危险的敌人&#xff0c;也是林业最可怕的灾害&#xff0c;它会给森林带来毁灭性的后果。 建设背景 森林火灾&#xff0c;重在预防。随着现代技术的快速发展&#xff0c;数字化森林监控已成为及早发觉&#xff0c;排除森林火灾隐情的必要手段。充分利用现代科…

C++ 指针数组

如果一个数组的每个元素都是指针变量&#xff0c;这个数组就是指针数组。指针数组的每个元素都必须是同一类型的指针。 1.一维指针数组 声明一维指针数组的语法形式&#xff1a; 数据类型*数组名[下标表达式];下标表达式指出数组元素的个数&#xff0c;数据类型确定每个元素…

【雕爷学编程】MicroPython动手做(29)——物联网之SIoT

知识点&#xff1a;什么是掌控板&#xff1f; 掌控板是一块普及STEAM创客教育、人工智能教育、机器人编程教育的开源智能硬件。它集成ESP-32高性能双核芯片&#xff0c;支持WiFi和蓝牙双模通信&#xff0c;可作为物联网节点&#xff0c;实现物联网应用。同时掌控板上集成了OLED…

浙大数据结构第六周之06-图3 六度空间

题目详情&#xff1a; “六度空间”理论又称作“六度分隔&#xff08;Six Degrees of Separation&#xff09;”理论。这个理论可以通俗地阐述为&#xff1a;“你和任何一个陌生人之间所间隔的人不会超过六个&#xff0c;也就是说&#xff0c;最多通过五个人你就能够认识任何一…

动手学深度学习—卷积神经网络(原理解释+代码详解)

目录 1. 从全连接层到卷积层2. 图像卷积2.1 互相关运算2.2 卷积层2.3 图像中目标的边缘检测2.4 学习卷积核2.5 特征映射和感受野 3. 填充和步幅3.1 填充3.2 步幅 4. 多输入多输出通道4.1 多输入通道4.2 多输出通道4.3 11卷积核 5. 汇聚层5.1 最大汇聚层和平均汇聚层5.2 填充和步…

Stable Diffusion - SDXL 模型测试 (DreamShaper 和 GuoFeng v4) 与全身图像参数配置

欢迎关注我的CSDN&#xff1a;https://spike.blog.csdn.net/ 本文地址&#xff1a;https://spike.blog.csdn.net/article/details/132085757 图像来源于 GuoFeng v4 XL 模型&#xff0c;艺术风格是赛博朋克、漫画、奇幻。 全身图像是指拍摄对象的整个身体都在画面中的照片&…

Bean的实例化方法

目录 1.工厂模式通常有三种形态&#xff1a; 2.简单工厂 2.1 静态工厂 2.1通过factory-bean实例化 2.3通过FactoryBean接口实例化 3.测试 关于容器的使用 3.1获得spring文件方式 3.2getBean方式 4.关闭容器 1.工厂模式通常有三种&#xff1a; 第一种&#xff1a;简单工…

二叉树题目:叶子相似的树

文章目录 题目标题和出处难度题目描述要求示例数据范围 解法一思路和算法代码复杂度分析 解法二思路和算法代码复杂度分析 题目 标题和出处 标题&#xff1a;叶子相似的树 出处&#xff1a;872. 叶子相似的树 难度 3 级 题目描述 要求 考虑一个二叉树上所有的叶子&…

消息队列项目(1)

概念 这里的消息队列, 大致上就是一个生产者消费者模型. 我这个消息队列是仿照 RabbitMQ 的实现原理来进行编写的 需求分析 有几个核心的概念: 生产者(Producer)消费者(Consumer)中间人(Broker)发布(Publish) :生产者向中间人投递消息的过程订阅(Subcribe) :记录哪些消费者…

Java面试题 如何提高自己的算法?

练习一&#xff1a;飞机票 需求:机票价格按照淡季旺季、头等舱和经济舱收费、输入机票原价、月份和头等舱或经济舱。 按照如下规则计算机票价格&#xff1a;旺季&#xff08;5-10月&#xff09;头等舱9折&#xff0c;经济舱8.5折&#xff0c;淡季&#xff08;11月到来年4月&a…

【Java可执行命令】(十五)Java进程状态信息获取工具 jps:获取和监控Java进程的状态信息 ~

Java可执行命令之jps 1️⃣ 概念2️⃣ 优势和缺点3️⃣ 使用3.1 语法格式3.2 可选参数&#xff1a;-q3.3 可选参数&#xff1a;-m3.4 可选参数&#xff1a;-l3.5 可选参数&#xff1a;-v3.6 可选参数&#xff1a;-V 4️⃣ 应用场景&#x1f33e; 总结 1️⃣ 概念 JPS&#xff…

【BEV感知】1-BEV感知算法介绍

1-BEV感知算法介绍 1 什么是BEV感知算法&#xff1f;1.1 什么是BEV&#xff1f;1.2 什么是感知&#xff1f;1.3 什么是算法&#xff1f;1.4 什么是BEV感知&#xff1f; 1 什么是BEV感知算法&#xff1f; 1.1 什么是BEV&#xff1f; Bird’s-Eye-View&#xff0c;尺度变化小、…

客户端电脑使用 FTP的Cadence_CIS库方法说明 (下)

简介&#xff1a;随着企业的规模扩大&#xff0c;硬件工程师的增多&#xff0c;使用统一服务器上的库管理&#xff0c;可以减少设计错误&#xff0c;提高效率。 使用在FTP上布局Cadence_CIS库&#xff0c;是目前的主流的做法之一&#xff1b; 本文方法&#xff0c;用于已经配置…