数据结构单链表

news2024/11/15 17:32:21

在这里插入图片描述

单链表
1 链表的概念及结构
概念:链表是一种物理存储结构上非连续、非顺序的存储结构,数据元素的逻辑顺序是通过链表中的指针链
接次序实现的 。

在我们开始讲链表之前,我们是写了顺序表,顺序表就是类似一个数组的东西,它的存放是连续的,优点有很多,比如支持我们随机访问,连续存放,命中率高,区别于单链表我们可以用类似数组的下标进行访问,这大大的提高我们的效率,但是也有缺点,空间不够就要需要扩容,扩容存在消耗的,头部或者中间位置的插入删除,需要挪动,挪动数据也是存在消耗的。避免频繁扩容,一次一般都是按倍数扩容,可能存在空间扩容。

链表的优点:
按需申请空间,不用释放空间。
头部或者中间位置的插入和删除,不需要挪动数据。
不存在空间浪费。

链表的缺陷:
每一个数据,都要存放一个指针去链表后面节点的地址。
不支持随机访问。

链表的结构

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;

这个就是我们单链表的基本代码,我们来用图更加清清楚的表示一下它完整的样子。
在这里插入图片描述
这就我们基本的逻辑结构,它前一个的next是存放后面的地址的,这样就能找到我们下一个节点。

单链表使用的时候相比和顺序表比较的话,它的使用不会浪费空间,我们需要一个节点就可以开辟一个节点出来供我们使用。但是它存储就不是连续的了。

那我们现在开始写代码来实现单链表。
单链表
首先我们要创建一个结构体。

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;

接下来我们首先要打印我们的单链表
在这之前我们应该创建节点,创捷节点很简单,就是按照我们上面的图的前一个存放后面的地址。

//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

那下面就是我们的打印单链表。

void SListPrint(SLNode* plist)
{
	SLNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");

}

我们来测试一下看看效果。

在这里插入图片描述
可以看到我们的单链表也是成功的打印,那接下来就是要写出我们的尾插函数。
写之前我们先来分析分析,首先尾插一个节点进去,那我们是不是要有一个这样的节点,竟然这样就可以写一个创造节点的函数。就叫他CreateSListNode

SLNode* CreateSListNode(SLNodedataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

写完这个那我们写一个尾插函数,尾插的时候我们要想一想要传什么地址过去,如果是有数据的话其实我们传一级地址就行,但是如果是空的话,就得传二级,因为我们要改变plist的位置。但是也其实是相当于头插,没节点的时候,总不能在空指针后面插入。那我们写一个 吧。

void SListPushBcak(SLNode** plist, SLNodedataType x)
{
	SLNode*newnode=CreateSListNode(x);
	assert(plist);

	if (*plist == NULL)
	{
		plist = newnode;
	}
	else
	{
		SLNode* tail = *plist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}

看一下我们编译的结果

在这里插入图片描述
最后也是成功的尾插进去,那尾插之后就应该要写一个尾删。
写尾删的时候,我们要先考虑怎么找到最后,这和尾插一样,遍历一遍找到最后一个,然后free掉就行了。

在这里插入图片描述
代码

void SListPopBack(SLNode** plist)
{
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}

这其实就是用了一个双指针的方法找最后一个的前一个,但是我们还需要注意链表不能为空,空了怎么删除啊。所以改进一下。

void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}
void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);
}

不过其实我们也可以不用双指针的办法。
那也整一个玩玩吧


void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	
	while (tail->next->next != NULL)
	{
		
		tail = tail->next;
	}
	free(tail->next);
	tail->next = NULL;
	

其实道理是一样的,就是找下下一个的节点是不是为空。
尾插写好就是头插,来吧展示。

void SListPushFront(SLNode** plist, SLNodedataType x)
{
	assert(plist);
	SLNode* newnode = CreateSListNode(x);
	if (*plist == NULL)
	{
		*plist = newnode;
	}
	else
	{
		newnode->next = *plist;
		*plist = newnode;
	}

}

其实想明白也不难,接下来就是头删。

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

}
void SListPopFront(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* cur = (*plist)->next;
	free(*plist);
	*plist = cur;
}

我们在写一个查找功能的代码

SLNode* SLFind(SLNode* plist, SLNodedataType x);

查找我们可以返回这个节点,这样就能和其他功能一起用,比如修改数据,或者在任意位置插入和删除。

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos->data == x)
	{
		return pos;
		pos = pos->next;
	}
}

这是只考虑找到的情况下,但是难免有时候会出现找不到的情况,让我们来看一下吧,写一个找不到情况下和找到情况下的代码。‘

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos != NULL)
	{
		if (pos->data == x)
		{
			return pos;
		}
		pos = pos->next;
	}
	return NULL;
}

然后我们可以写一个函数来判断有没有找到。

SLNode*pos = SLFind(n1, 111);
	if (pos != NULL)
	{
		printf("找到了\n");
	}
	else
	{
		printf("找不到\n");
	}

我们看完整代码。

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1, 111);
	if (pos != NULL)
	{
		printf("找到了\n");
	}
	else
	{
		printf("找不到\n");
	}

}

我们如果要找111发现没有找到,因为头删的时候改掉,其实我们竟然这样写了就可以写一个修改的代码,这里就不演示了。
接下来我们要写的是在任意位置删除和插入节点。

void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x)
{
	assert(plist);
	assert(pos);
	SLNode* newnode = CreateSListNode(x);
	if (pos == *plist)
	{
		SListPushFront(plist, x);
	}
	
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;

	}
}

测试代码

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1,3);
	if (pos != NULL)
	{
		printf("找到了\n");
		SListPushInsert(&n1, pos, 10086);
	}
	else
	{
		printf("找不到\n");
	}
	SListPrint(n1);
}

在任意位置删除

void SListPopInsert(SLNode** plist, SLNode* pos)
{
	assert(plist);
	assert(*plist);
	assert(pos);
	if (*plist == pos)
	{
		SListPopFront(plist);
	}
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

其实还有可以在任意位置后删除,这样更快,就不用找那个位置前一个位置了,这里就不展示了,
完整代码

#define _CRT_SECURE_NO_WARNINGS 1

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

typedef int SLNodedataType;
typedef struct SList
{
	SLNodedataType data;
	struct SList* next;
	
}SLNode;


void SListPrint(SLNode* plist);

SLNode* CreateSListNode(SLNodedataType x);


void SListPushBcak(SLNode** plist, SLNodedataType x);

void SListPopBack(SLNode** plist);

void SListPushFront(SLNode** plist, SLNodedataType x);

void SListPopFront(SLNode** plist);

SLNode* SLFind(SLNode* plist, SLNodedataType x);

void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x);

void SListPopInsert(SLNode** plist, SLNode* pos);


#include"SList.h"

void SListPrint(SLNode* plist)
{
	SLNode* cur = plist;
	while (cur != NULL)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL");
	printf("\n");

}





SLNode* CreateSListNode(SLNodedataType x)
{
	SLNode* newnode = (SLNode*)malloc(sizeof(SLNode));
	newnode->data = x;
	newnode->next = NULL;
	return newnode;
}

void SListPushBcak(SLNode** plist, SLNodedataType x)
{
	SLNode*newnode=CreateSListNode(x);
	assert(plist);

	if (*plist == NULL)
	{
		plist = newnode;
	}
	else
	{
		SLNode* tail = *plist;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}
		tail->next = newnode;
	}

}


void SListPopBack(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* tail = *plist;
	SLNode* prev = NULL;
	while (tail->next != NULL)
	{
		prev = tail;
		tail = tail->next;
	}
	free(tail);
	prev->next = NULL;
}
//
//void SListPopBack(SLNode** plist)
//{
//	assert(plist);
//	assert(*plist);
//	SLNode* tail = *plist;
//	
//	while (tail->next->next != NULL)
//	{
//		
//		tail = tail->next;
//	}
//	free(tail->next);
//	tail->next = NULL;
//	
//}



void SListPushFront(SLNode** plist, SLNodedataType x)
{
	assert(plist);
	SLNode* newnode = CreateSListNode(x);
	if (*plist == NULL)
	{
		*plist = newnode;
	}
	else
	{
		newnode->next = *plist;
		*plist = newnode;
	}

}

void SListPopFront(SLNode** plist)
{
	assert(plist);
	assert(*plist);
	SLNode* cur = (*plist)->next;
	free(*plist);
	*plist = cur;
}


//SLNode* SLFind(SLNode* plist, SLNodedataType x)
//{
//	SLNode* pos = plist;
//	while (pos->data == x)
//	{
//		return pos;
//		pos = pos->next;
//	}
//}

SLNode* SLFind(SLNode* plist, SLNodedataType x)
{
	SLNode* pos = plist;
	while (pos != NULL)
	{
		if (pos->data == x)
		{
			return pos;
		}
		pos = pos->next;
	}
	return NULL;
}


void SListPushInsert(SLNode** plist, SLNode* pos, SLNodedataType x)
{
	assert(plist);
	assert(pos);
	SLNode* newnode = CreateSListNode(x);
	if (pos == *plist)
	{
		SListPushFront(plist, x);
	}
	
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = newnode;
		newnode->next = pos;

	}
}

void SListPopInsert(SLNode** plist, SLNode* pos)
{
	assert(plist);
	assert(*plist);
	assert(pos);
	if (*plist == pos)
	{
		SListPopFront(plist);
	}
	else
	{
		SLNode* prev = *plist;
		while (prev->next != pos)
		{
			prev = prev->next;
		}
		prev->next = pos->next;
		free(pos);
	}
}

测试主函数的也发一下吧,大家可以不用放一起测试,有点看不过来。

#include"SList.h"

void test1()
{
	//创建节点
	SLNode* n1 = (SLNode*)malloc(sizeof(SLNode));
	assert(n1);
	SLNode* n2 = (SLNode*)malloc(sizeof(SLNode));
	assert(n2);
	SLNode* n3 = (SLNode*)malloc(sizeof(SLNode));
	assert(n3);
	SLNode* n4 = (SLNode*)malloc(sizeof(SLNode));
	assert(n4);
	n1->data = 1;
	n2->data = 2;
	n3->data = 3;
	n4->data = 4;

	n1->next = n2;
	n2->next = n3;
	n3->next = n4;
	n4->next = NULL;

	SListPrint(n1);

	SListPushBcak(&n1, 5);
	SListPushBcak(&n1, 6);
	SListPushBcak(&n1, 7);
	SListPushBcak(&n1, 8);
	SListPrint(n1);
	SListPopBack(&n1);
	SListPopBack(&n1);
	SListPrint(n1);

	SListPushFront(&n1, 111);
	SListPushFront(&n1, 222);
	SListPrint(n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPopFront(&n1);
	SListPrint(n1);

	SLNode*pos = SLFind(n1,3);
	if (pos != NULL)
	{
		printf("找到了\n");
		SListPushInsert(&n1, pos, 10086);
	}
	else
	{
		printf("找不到\n");
	}
	SListPrint(n1);
}
int main()
{
	test1();
	return 0;
}

今天的分享就到这里,我们下次再见。

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

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

相关文章

651页23万字智慧教育大数据信息化顶层设计及建设方案WORD

导读&#xff1a;原文《651页23万字智慧教育大数据信息化顶层设计及建设方案WORD》&#xff08;获取来源见文尾&#xff09;&#xff0c;本文精选其中精华及架构部分&#xff0c;逻辑清晰、内容完整&#xff0c;为快速形成售前方案提供参考。 目录 一、 方案背景 1.1 以教育…

三、数据类型

1、数值类型 &#xff08;1&#xff09;分类&#xff1a; &#xff08;2&#xff09;注意&#xff1a; 存储某一类数据&#xff0c;如果只想要表示整数&#xff0c;则在其后加unsigned即可&#xff1b; 在表示小数时&#xff0c;需要指明该小数的总长度和小数部分的长度&…

PostgreSQL空值的判断

PostgreSQL空值的判断 空值判断非空判断总结 空值判断 -- 查询为空的 is null,sql简写isnull select * from employees where manager_id isnull;select * from employees where manager_id is null;非空判断 -- 查询不为空的 is not null;sql简写notnull select * from empl…

c++基本语法

c基础语法 由于长时间没有使用过c&#xff0c;因此c的语法已经忘得差不多了&#xff0c;这篇文章主要是快读地过一遍c的基本语法。之前也写过一篇从c过渡到c的文章&#xff0c;有兴趣地可以看看。 文章链接 1.c的安装 mingw64的安装配置环境变量 2.语法 #include<iostre…

leetcode 力扣刷题 两数/三数/四数之和 哈希表和双指针解题

两数/三数/四数之和 题目合集 哈希表求解1. 两数之和454. 四数相加Ⅱ 双指针求解15.三数之和18. 四数之和 这个博客是关于&#xff1a;找出数组中几个元素&#xff0c;使其之和等于题意给出的target 这一类题目的&#xff0c;但是各个题之间又有些差异&#xff0c;使得需要用不…

网络及其计算的重点知识及回顾

概述 1.1 计算机网络的分类 按照网络的作用范围&#xff1a;广域网&#xff08;WAN&#xff09;、城域网&#xff08;MAN&#xff09;、局域网&#xff08;LAN&#xff09;&#xff1b; 按照网络使用者&#xff1a;公用网络、专用网络。 1.2 计算机网络的层次结构 应用层&a…

谷歌云平台替代超级计算机?助力心脏病学研究,省心智能还省钱

哈佛大学的研究团队在使用谷歌云平台代替超级计算机进行心脏病研究方面取得了重大突破。通常情况下&#xff0c;进行模拟人体循环系统中血块和肿瘤细胞的疗法需要强大的计算能力才能提供准确的结果。然而&#xff0c;超级计算机的高昂成本和有限的可用性成为这项研究面临的巨大…

Qt+Pyhton实现麒麟V10系统下word文档读写功能

目录 前言1.C调用python1.1 安装Python开发环境1.2 修改Qt工程配置1.3 初始化Python环境1.4 C 调用Python 函数1.5 常用的Python接口 2.python虚拟环境2.1Python虚拟环境简介2.2 virtualenv 安装及使用2.3 在C程序中配置virtualenv 虚拟环境 3.python-docx库的应用4.总结 前言 …

【计算机网络篇】UDP协议

✅作者简介&#xff1a;大家好&#xff0c;我是小杨 &#x1f4c3;个人主页&#xff1a;「小杨」的csdn博客 &#x1f433;希望大家多多支持&#x1f970;一起进步呀&#xff01; UDP协议 1&#xff0c;UDP 简介 UDP&#xff08;User Datagram Protocol&#xff09;是一种无连…

集成DTM实现跨语言分布式事务V1.0

集成DTM实现跨语言分布式事务V1.0 简介 DTM是一款开源的分布式事务管理器&#xff0c;解决跨数据库、跨服务、跨语言栈更新数据的一致性问题。 通俗一点说&#xff0c;DTM提供跨服务事务能力&#xff0c;一组服务要么全部成功&#xff0c;要么全部回滚&#xff0c;避免只更新…

Qt编程基础 | 第六章-窗体 | 6.5、QTableWidget 使用过程注意的问题

一、QTableWidget 使用过程注意的问题 1、添加行时要先设置行数 往表格重添加行时&#xff0c;要先设置行数&#xff0c;不然添加的内容看不到&#xff0c;如下&#xff1a; void QCustomWidget::InitTableContent() {for (int row 0; row < m_rowData.size(); row ){// 注…

DAY4,ARM(用c语言点亮LED灯,封装库代码,软件编程控制硬件)

---gpio.h头文件--- #ifndef __LED_H__ #define __LED_H__//1RCC_MP_AHB4ENSETR寄存器封装 #define RCC_MP_AHB4ENSETR (*(volatile unsigned int*)0x50000a28)//2GPIO封装结构体 typedef struct {volatile unsigned int MODER;volatile unsigned int OTYPER;volatile unsigne…

Python系统学习1-9-类二之MVC框架

一、模型说明 View视图:处理界面逻辑,输入输出 Controller控制器:处理核心逻辑,存储计算 Model模型:将多个变量组合为一种类型 二、注意事项 类外通过自定义对象名调用 类中通过self调用 """疫情信息管理系统学习MVC的软件架构View Controller Model视…

汇川脉冲伺服SV630P常用参数设置(博途PLC脉冲输出控制)

有关博途PLC脉冲输出控制功能块详细介绍,请查看下面博客链接: 博途1200PLC轴控功能块(脉冲轴)_博图 轴控块_RXXW_Dor的博客-CSDN博客STRUCT// 轴使能// 轴正向点动// 轴反向点动// 轴回原// 轴复位// 轴暂停// 轴快速停机// 轴绝对定位// 轴相对定位// 轴匀速运行// 修改轴参…

Dubbo基础学习

目录 第一章、概念介绍1.1&#xff09;什么是RPC框架1.2&#xff09;什么是分布式系统1.3&#xff09;Dubbo概述1.3&#xff09;Dubbo基本架构 第二章、服务提供者(直连)2.1&#xff09;目录结构和依赖2.2&#xff09;model层2.3&#xff09;service层2.4&#xff09;resources…

Java课题笔记~ 日期处理

2.8 日期处理 2.8.1 日期注入 日期类型不能自动注入到方法的参数中。需要单独做转换处理。 使用DateTimeFormat注解&#xff0c;需要在springmvc.xml文件中添加mvc:annotation-driven/标签。 &#xff08;1&#xff09;在方法的参数上使用DateTimeFormat注解 RequestMappi…

浅谈SPA

1. 基本概念 ● SPA(single-page application) 单页应用,默认情况下我们编写Vue,React都只有一个html页面并且提供一个挂载点,最终打包后会在此页面中引入对应的资源.(页面渲染全部由js动态进行渲染).切换页面时通过监听路由变化,渲染对应的页面(client side rendering,客户端…

探秘分布式大数据:融合专业洞见,燃起趣味火花,启迪玄幻思维

文章目录 一 数据导论二 大数据的诞生三 大数据概论3.1 大数据的5V特征3.2 大数据的工作核心 四 大数据软件生态4.1 数据存储软件4.2 数据计算软件4.3 数据传输软件 五 Apache Hadoop概述5.1 Apache Hadoop框架5.2 Hadoop的功能5.3 Hadoop的发展5.4 Hadoop发行版本 一 数据导论…

使用Python批量将Word文件转为PDF文件

说明&#xff1a;在使用Minio服务器时&#xff0c;无法对word文件预览&#xff0c;如果有需要的话&#xff0c;可以将word文件转为pdf文件&#xff0c;再存储到Minio中&#xff0c;本文介绍如果批量将word文件&#xff0c;转为pdf格式的文件&#xff1b; 安装库 首先&#xff…