单链表专题

文章目录

  • 目录
    • 1. 链表的概念及结构
    • 2. 实现单链表
      • 2.1 链表的打印
      • 2.2 链表的尾插
      • 2.3 链表的头插
      • 2.4 链表的尾删
      • 2.5 链表的头删
      • 2.6 查找
      • 2.7 在指定位置之前插入数据
      • 2.8 在指定位置之后插入数据
      • 2.9 删除pos节点
      • 2.10 删除pos之后的节点
      • 2.11 销毁链表
    • 3. 链表的分类

目录

  • 链表的概念及结构
  • 实现单链表
  • 链表的分类

1. 链表的概念及结构

概念:

链表是⼀种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链接次序实现的(链表在逻辑上是连续的,在物理结构上不一定连续) 。

链表的结构
链表是由一个一个节点(结点)组成的,一个节点由两个部分组成:要存储的数据 + 指针(结构体指针)

因此,只要定义节点的结构,就等于定义了链表:

typedef int SLTDataType;

//链表是由节点组成
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

2. 实现单链表

2.1 链表的打印

void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;

	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}

	printf("NULL\n");
}

2.2 链表的尾插

void SLTPushBack(SLTNode* phead, SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->data = x;
	newnode->next = NULL;
	
	//链表为空,新节点作为phead
	if (NULL == phead)
	{
		phead = newnode;
		return;
	}
	
	//链表不为空,找尾节点
	SLTNode* ptail = phead;

	while (ptail->next)
	{
		ptail = ptail->next;
	}

	//ptail就是尾节点
	ptail->next = newnode;
}

这样写是错误的!当一开始链表为空时,尾插的节点就变成了第一个节点,因此要把phead中的NULL改为第一个节点的地址,所以要传phead的地址,而不是传值。

应该这样写:

//因为头插、尾插、指定位置插入都需要申请新节点,所以单独封装成一个函数
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	
	if (NULL == newnode)
	{
		perror("malloc fail!");
		exit(1);
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	SLTNode* newnode = SLTBuyNode(x);

	//链表为空,新节点作为phead
	if (NULL == *pphead)
	{
		*pphead = newnode;
		return;
	}

	//链表不为空,找尾节点
	SLTNode* ptail = *pphead;

	while (ptail->next)
	{
		ptail = ptail->next;
	}

	//ptail就是尾节点
	ptail->next = newnode;
}

2.3 链表的头插

void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	SLTNode* newnode = SLTBuyNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}

2.4 链表的尾删

void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);

	//链表不为空
	//链表只有一个节点,有多个节点
	if (NULL == (*pphead)->next)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}

	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;

	while (ptail->next)
	{
		prev = ptail;
		ptail = ptail->next;
	}

	prev->next = NULL;
	//销毁尾节点
	free(ptail);
	ptail = NULL;
}

2.5 链表的头删

void SLTPopFront(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);

	//让第二个节点成为新的头
	//把旧的头节点释放掉
	SLTNode* next = (*pphead)->next;//->的优先级高于*
	free(*pphead);
	*pphead = next;
}

2.6 查找

SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	//遍历链表
	SLTNode* pcur = *pphead;

	while (pcur) //等价于pcur != NULL
	{
		if (pcur->data == x)
		{
			return pcur;
		}

		pcur = pcur->next;
	}

	//没有找到
	return NULL;
}

2.7 在指定位置之前插入数据

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	//要加上链表不能为空
	assert(*pphead);

	SLTNode* newnode = SLTBuyNode(x);

	//pos刚好是头节点
	if (pos == *pphead)
	{
		//头插
		SLTPushFront(pphead, x);
		return;
	}

	//pos不是头节点的情况
	SLTNode* prev = *pphead;

	while (prev->next != pos)
	{
		prev = prev->next;
	}

	//prev -> newnode -> pos
	prev->next = newnode;
	newnode->next = pos;
}

2.8 在指定位置之后插入数据

void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);

	SLTNode* newnode = SLTBuyNode(x);

	newnode->next = pos->next;
	pos->next = newnode;
}

2.9 删除pos节点

void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);

	//pos刚好是第一个节点,没有前驱节点,执行头删
	if (*pphead == pos)
	{
		//头删
		SLTPopFront(pphead);
		return;
	}

	SLTNode* prev = *pphead;

	while (prev->next != pos)
	{
		prev = prev->next;
	}

	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

2.10 删除pos之后的节点

void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);
	//pos->next不能为空
	assert(pos->next);

	SLTNode* del = pos->next;
	pos->next = pos->next->next;
	free(del);
	del = NULL;
}

2.11 销毁链表

void SListDesTroy(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);

	SLTNode* pcur = *pphead;

	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}

	*pphead = NULL;
}

完整代码:

//SList.h

#include <stdio.h>
#include <stdlib.h>
#include <assert.h>

typedef int SLTDataType;

//链表是由节点组成
typedef struct SListNode
{
	SLTDataType data;
	struct SListNode* next;
}SLTNode;

void SLTPrint(SLTNode* phead);

//链表的头插、尾插
//void SLTPushBack(SLTNode* phead, SLTDataType x);//err
void SLTPushBack(SLTNode** pphead, SLTDataType x);
void SLTPushFront(SLTNode** pphead, SLTDataType x);

//链表的头删、尾删
void SLTPopBack(SLTNode** pphead);
void SLTPopFront(SLTNode** pphead);

//查找
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x);

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x);

//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos);

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos);

//销毁链表
void SListDesTroy(SLTNode** pphead);
//SList.c

#include "SList.h"

void SLTPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;

	while (pcur)
	{
		printf("%d->", pcur->data);
		pcur = pcur->next;
	}

	printf("NULL\n");
}

//因为头插、尾插、指定位置插入都需要申请新节点,所以单独封装成一个函数
SLTNode* SLTBuyNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	
	if (NULL == newnode)
	{
		perror("malloc fail!");
		exit(1);
	}

	newnode->data = x;
	newnode->next = NULL;

	return newnode;
}

void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	SLTNode* newnode = SLTBuyNode(x);

	//链表为空,新节点作为phead
	if (NULL == *pphead)
	{
		*pphead = newnode;
		return;
	}

	//链表不为空,找尾节点
	SLTNode* ptail = *pphead;

	while (ptail->next)
	{
		ptail = ptail->next;
	}

	//ptail就是尾节点
	ptail->next = newnode;
}


void SLTPushFront(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	SLTNode* newnode = SLTBuyNode(x);

	newnode->next = *pphead;
	*pphead = newnode;
}


void SLTPopBack(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);

	//链表不为空
	//链表只有一个节点,有多个节点
	if (NULL == (*pphead)->next)
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}

	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;

	while (ptail->next)
	{
		prev = ptail;
		ptail = ptail->next;
	}

	prev->next = NULL;
	//销毁尾节点
	free(ptail);
	ptail = NULL;
}


void SLTPopFront(SLTNode** pphead)
{
	assert(pphead);
	//链表不能为空
	assert(*pphead);

	//让第二个节点成为新的头
	//把旧的头节点释放掉
	SLTNode* next = (*pphead)->next;//->的优先级高于*
	free(*pphead);
	*pphead = next;
}


//查找
SLTNode* SLTFind(SLTNode** pphead, SLTDataType x)
{
	assert(pphead);

	//遍历链表
	SLTNode* pcur = *pphead;

	while (pcur) //等价于pcur != NULL
	{
		if (pcur->data == x)
		{
			return pcur;
		}

		pcur = pcur->next;
	}

	//没有找到
	return NULL;
}


//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);
	//要加上链表不能为空
	assert(*pphead);

	SLTNode* newnode = SLTBuyNode(x);

	//pos刚好是头节点
	if (pos == *pphead)
	{
		//头插
		SLTPushFront(pphead, x);
		return;
	}

	//pos不是头节点的情况
	SLTNode* prev = *pphead;

	while (prev->next != pos)
	{
		prev = prev->next;
	}

	//prev -> newnode -> pos
	prev->next = newnode;
	newnode->next = pos;
}

//在指定位置之后插入数据
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);

	SLTNode* newnode = SLTBuyNode(x);

	newnode->next = pos->next;
	pos->next = newnode;
}


//删除pos节点
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);

	//pos刚好是第一个节点,没有前驱节点,执行头删
	if (*pphead == pos)
	{
		//头删
		SLTPopFront(pphead);
		return;
	}

	SLTNode* prev = *pphead;

	while (prev->next != pos)
	{
		prev = prev->next;
	}

	prev->next = pos->next;
	free(pos);
	pos = NULL;
}

//删除pos之后的节点
void SLTEraseAfter(SLTNode* pos)
{
	assert(pos);
	//pos->next不能为空
	assert(pos->next);

	SLTNode* del = pos->next;
	pos->next = pos->next->next;
	free(del);
	del = NULL;
}


//销毁链表
void SListDesTroy(SLTNode** pphead)
{
	assert(pphead);
	assert(*pphead);

	SLTNode* pcur = *pphead;

	while (pcur)
	{
		SLTNode* next = pcur->next;
		free(pcur);
		pcur = next;
	}

	*pphead = NULL;
}
//Test.c

//int removeElement(int* nums, int numsSize, int val)
//{
//	//定义两个变量
//	int src = 0, dst = 0;
//
//	while (src < numsSize)
//	{
//		//nums[src] == val,src++
//		//否则赋值,src和dst都++
//		if (nums[src] == val)
//		{
//			src++;
//		}
//		else
//		{
//			//说明src指向位置的值不等于val
//			nums[dst] = nums[src];
//			dst++;
//			src++;
//		}
//	}
//
//	//此时dst的值刚好是数组的新长度
//	return dst;
//}




//void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
//{
//	int l1 = m - 1;
//	int l2 = n - 1;
//	int l3 = m + n - 1;
//
//	while (l1 >= 0 && l2 >= 0)
//	{
//		//从后往前比大小
//		if (nums1[l1] > nums2[l2])
//		{
//			nums1[l3--] = nums1[l1--];
//		}
//		else
//		{
//			nums1[l3--] = nums2[l2--];
//		}
//	}
//
//	//要么是l1 < 0,要么是l2 < 0
//	while (l2 >= 0)
//	{
//		nums1[l3--] = nums2[l2--];
//	}
//}



#include "SList.h"

void SListTest01()
{
	//一般不会这样去创建链表,这里只是为了给大家展示链表的打印
	SLTNode* node1 = (SLTNode*)malloc(sizeof(SLTNode));
	node1->data = 1;
	SLTNode* node2 = (SLTNode*)malloc(sizeof(SLTNode));
	node2->data = 2;
	SLTNode* node3 = (SLTNode*)malloc(sizeof(SLTNode));
	node3->data = 3;
	SLTNode* node4 = (SLTNode*)malloc(sizeof(SLTNode));
	node4->data = 4;

	node1->next = node2;
	node2->next = node3;
	node3->next = node4;
	node4->next = NULL;

	SLTNode* plist = node1;
	SLTPrint(plist);
}

void SListTest02()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);

	//SLTPushBack(NULL, 5);

	//SLTPushFront(&plist, 5);
	//SLTPrint(plist);
	//SLTPushFront(&plist, 6);
	//SLTPrint(plist);
	//SLTPushFront(&plist, 7);
	//SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);
	SLTPopBack(&plist);
	SLTPrint(plist);
	SLTPopBack(&plist);
	SLTPrint(plist);
	SLTPopBack(&plist);
	SLTPrint(plist);
	//SLTPopBack(&plist);
	//SLTPrint(plist);
}

void SListTest03()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPrint(plist);

	//头删
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	//SLTPopFront(&plist);
	//SLTPrint(plist);
	SLTPopFront(&plist);
	SLTPrint(plist);

	//SLTNode* FindRet = SLTFind(&plist, 3);

	if (FindRet)
	{
		printf("找到了!\n");
	}
	else
	{
		printf("未找到!\n");
	}

	SLTInsert(&plist, FindRet, 100);
	SLTPrint(plist);

	SLTInsertAfter(FindRet, 100);
	SLTPrint(plist);

	删除指定位置的节点
	//SLTErase(&plist, FindRet);
	//SLTPrint(plist);

	SListDesTroy(&plist);
}


int main()
{
	//SListTest01();
	//SListTest02();
	SListTest03();

	return 0;
}

3. 链表的分类

链表的结构非常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构:
链表的分类
链表说明:
链表说明
注:

  1. 之前代码里写的 SList 意思是 single linked list --> 单链表(不带头单向不循环链表
  2. 刚才在单链表中提到的“头节点”指的是第一个有效的节点;“带头”链表里的“头”指的是无效的节点
  3. “带头”中的“头”:放哨的;头节点:哨兵位(不保存任何有效的数据)

虽然有这么多的链表的结构,但是我们实际中最常用还是两种结构:单链表和双向带头循环链表。

  1. 无头单向非循环链表:结构简单,⼀般不会单独用来存数据,实际中更多是作为其他数据结构的子结构,如哈希桶、图的邻接表等等;另外这种结构在笔试面试中出现很多。
  2. 带头双向循环链表:结构最复杂,⼀般用在单独存储数据,实际中使用的链表数据结构,都是带头双向循环链表;另外这个结构虽然结构复杂,但是使用代码实现以后会发现结构会带来很多优势,实现反而简单了,后面我们代码实现了就知道了。

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

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

相关文章

设计模式学习笔记 - 设计模式与范式 -行为型:10.迭代器模式(中):遍历集合时,为什么不能增删集合?

概述 上篇文章&#xff0c;我们通过给 ArrayList 和 LinkedList 容器实现迭代器&#xff0c;学习了迭代器模式的原理、实现和设计意图。迭代器模式主要主要是解耦容器代码和遍历代码。 本章&#xff0c;我们来深挖一下&#xff0c;如果在使用迭代器遍历集合的同时增加、删除集…

无尘净化棉签:清洁革新的里程碑

随着科技的不断进步&#xff0c;日常生活中的许多小物件也在不断地得到创新和改良。其中&#xff0c;棉签作为一种常见的清洁工具&#xff0c;经历了从传统到现代的革新&#xff0c;引入了无尘棉签的概念&#xff0c;为清洁领域带来了一场革命性的变革。本文优斯特将探讨无尘棉…

运维工具-Backup集合

RepositoryLicenseStarCreatedAtUpdatedAtDescriptionjeessy2/backup-xMIT2842021-11-132023-12-15带Web界面的数据库/文件备份增强工具noovertime7/gin-mysqlbakMIT382022-06-212023-02-06一款分布式高性能的备份系统&#xff0c;支持 MySQL、ElasticSearch 备份&#xff0c;多…

《高通量测序技术》分享,生物信息学生信流程的性能验证,以肿瘤NGS基因检测为例。

这是这本书&#xff0c;第四章第五节的内容&#xff0c;这一部分是以NGS检测肿瘤基因突变为例&#xff0c;描述了其原理和大概流程&#xff0c;这和以前我分享的病原宏基因组高通量测序性能确认方案可以互相补充&#xff0c;大家可以都看一下&#xff0c;但是想要真正的弄懂&am…

【Leetcode】1702. 修改后的最大二进制字符串

文章目录 题目思路代码复杂度分析时间复杂度空间复杂度 结果总结 题目 题目链接&#x1f517; 给你一个二进制字符串 b i n a r y binary binary &#xff0c;它仅有 0 0 0 或者 1 1 1 组成。你可以使用下面的操作任意次对它进行修改&#xff1a; 操作 1 &#xff1a;如果…

背 单 词

单词&#xff1a; 买考研词汇闪过 研究艾宾浩斯遗忘曲线 https://www.bilibili.com/video/BV18Y4y1h7YR/?spm_id_from333.337.search-card.all.click&vd_source5cbefe6dd70d6d84830a5891ceab2bf9 单词方法 闪记背两排&#xff08;5min&#xff09;重复一遍&#xff08;2mi…

解决Can‘t connect to HTTPS URL because the SSL module is not available

把C:\develop\An3\Library\bin的这些文件&#xff0c;复制到C:\develop\An3\DLLs中

2006年重邮801信号与系统考研真题与详解

本系列文章为重庆邮电大学801信号与系统考研真题与详解&#xff0c;前面文章链接如下&#xff1a; 2003年重邮801信号与系统考研真题与详解 2004年重邮801信号与系统考研真题与详解 2005年重邮801信号与系统考研真题与详解 文章目录 前言一对一极速提分辅导2006年重邮801信号与…

基于GAN的图像补全实战

数据与代码地址见文末 论文地址:http://iizuka.cs.tsukuba.ac.jp/projects/completion/data/completion_sig2017.pdf 1.概述 图像补全,即补全图像中的覆盖和缺失部分, 网络整体结构如下图所示,整体网络结构还是采取GAN,对于生成器,网络结构采取Unet的形式,首先使用卷积…

字节发布AnimateDiff-Lightning文生视频模型——可在线免费试玩

Sora文生视频大模型 随着Sora文生视频大模型的爆火&#xff0c;文生视频大模型必定是各大人工智能公司竞争的主要领域。虽然 Sora模型的视频效果绝对是领先地位&#xff0c;但是Sora模型目前还没有开放使用&#xff0c;我们并无法直接使用。前期我们也介绍过字节发布的MagicVi…

【优选算法专栏】专题十三:队列+宽搜(一)

本专栏内容为&#xff1a;算法学习专栏&#xff0c;分为优选算法专栏&#xff0c;贪心算法专栏&#xff0c;动态规划专栏以及递归&#xff0c;搜索与回溯算法专栏四部分。 通过本专栏的深入学习&#xff0c;你可以了解并掌握算法。 &#x1f493;博主csdn个人主页&#xff1a;小…

C++ 线程库(thread)与锁(mutex)

一.线程库(thread) 1.1 线程类的简单介绍 thread类文档介绍 在C11之前&#xff0c;涉及到多线程问题&#xff0c;都是和平台相关的&#xff0c;比如windows和linux下各有自己的接口&#xff0c;这使得代码的可移植性比较差。C11中最重要的特性就是对线程进行支持了&#xff…

群联AI云防护中的防盗链技术原理及其作用探析---

一、引言 随着云计算和AI技术的快速发展&#xff0c;云防护方案已经成为现代企业防范网络攻击和保护数字资产的重要手段之一。群联科技作为存储解决方案和技术服务的领导者&#xff0c;已将其AI技术应用于云端防护系统中&#xff0c;并特别强化了防盗链功能&#xff0c;以帮助…

element-plus blur和select冲突失效导致移除焦点清空文本框内容失效解决方案

问题 需求是做一个查询企业的功能&#xff0c;期望必须进行选择后进行查询&#xff0c;如果用户自主输入并没有进行选择&#xff0c;失去焦点的时候清空文本框里面的内容&#xff0c;给el-autocomplete添加blur事件后发现&#xff0c;在下拉没有出现之前快速失去焦点才能触发b…

SuperGluePretrainedNetwork调用接口版本(两个版本!)

本脚本是一个基于Python的应用&#xff0c;旨在演示如何使用SuperGlue算法进行图像之间的特征匹配。SuperGlue是一个强大的特征匹配工具&#xff0c;能够在不同的图像之间找到对应的关键点。这个工具尤其适用于计算机视觉任务&#xff0c;如立体视觉、图像拼接、对象识别和追踪…

express操作mysql数据库的方法总结

作为前端&#xff0c;我们无需去考虑数据库的问题&#xff0c;业务场景需要的话&#xff0c;我们可以mock数据&#xff0c;满足暂时的联调场景。但是对于数据库&#xff0c;我们前端可以不用&#xff0c;却不能不了解不懂。所以这篇文章整理下&#xff0c;nodejs框架express中怎…

【通信原理笔记】【三】模拟信号调制——3.5 角度调制(FM、PM)与其频谱特性

文章目录 前言一、相位与频率二、PM和FM的数学表示三、FM的频谱四、FM信号的带宽——卡松公式总结 前言 在之前介绍的几种调制方式中&#xff0c;我提到信噪比时计算的是用户解调后的信噪比&#xff0c;然而在北邮通信原理课中考虑的是解调器输入的信噪比&#xff0c;即考虑的…

H-GAP: Humanoid Control with a Generalist Planner

ICLR 2024 paper Intro 本文方法研究利用大量人类动捕数据以及衍生的类人轨迹数据&#xff0c;基于MPC实现下游任务中机器人运动控制。 method H-GAP 的算法框架分为三个部分&#xff1a;基于VQ-VAE对状态动作序列的离散化&#xff0c;基于Transformer对latent code的先验…

爬虫 新闻网站 以湖南法治报为例(含详细注释,控制台版) V2.0 升级自定义查询关键词、时间段

目标网站&#xff1a;湖南法治报 爬取目的&#xff1a;为了获取某一地区更全面的在湖南法治报已发布的宣传新闻稿&#xff0c;同时也让自己的工作更便捷 环境&#xff1a;Pycharm2021&#xff0c;Python3.10&#xff0c; 安装的包&#xff1a;requests&#xff0c;csv&#xff…

uniapp 2.0可视化开发工具高级事件使用技巧探索

摘要 随着移动应用市场的不断扩大和前端技术的飞速发展&#xff0c;开发者们对于快速、高效构建跨平台应用的需求日益增强。uniapp作为一款优秀的跨平台应用开发框架&#xff0c;凭借其强大的功能和易用的特性&#xff0c;赢得了广大开发者的青睐。在uniapp 2.0版本中&#xf…