初阶数据结构(三)链表

news2024/11/24 3:28:12

💓博主csdn个人主页:小小unicorn💓
⏩专栏分类:c++
🚚代码仓库:小小unicorn的学习足迹🚚
🌹🌹🌹关注我带你学习编程知识

前面我们讲的线性表的顺序存储结构。它是有缺点的,最大的缺点就是插入和删除时需要移动大量元素,这显然就需要耗费时间,那能不能想办法解决呢?
要解决这个问题,我们就得考虑一下导致这个问题的大致原因:
为什么当插入和制除时,就要移动大量元素?仔细分析后,发现原因就在于自元素的存储位置也具有邻居关系。它们编号是1,2,3,…,n,它们在内存中的位最的是按着的,中间没有空源,当然就无法快速插入,而删除后,当中就会留出空像,自然需要弥补。问题就出在这里

A同学思路:让当中每个元素之间都留有一个空位置,这样要插入时,就不至于动,可一个空位置如何解决多个相同位置插入数据的问题呢?所以这个想法显然不行。

B同学思路:那就让当中每个元素之间都留足够多的位置,根据实际情况制定空像大小,比如10个,这样插入时,就不需要移动了。万一10个空位用完了,再考虑移动使得每个位置之间都有10个空位置。如果删除,就直接删掉,把位置留空即可。这样似乎蓄时解决了插入和删除的移动数据问题。可这对于超过10个同位置数据的插入,效率上还是存在问题。对于数据的遍历,也会因为空位置太多而造成判断时间上的浪费。而且显然这里空间复杂度还增加了,因为每个元素之间都有若干个空位置。

C同学思路:我们反正也是要让相邻元素间留有足够余地,那干脆所有的元素都不要考虑相邻位置了,哪有空位就到哪里,而只是让每个元素知道它下一个元素的位置在哪里,这样,我们可以在第一个元素时,就知道第二个元素的位置(内存地址),而找到它:在第二个元素时,再找到第三个元素的位置(内存地址)。这样所有的元素我们就都可以通过遍历而找到。
好!大棒了,这个想法非常好!

C同学,可惜生晚了几十年,不然,c同学的想法对于数据结构来讲就是划时代的意义。我们要的就是这个思路。

链表

  • 1.线性表的联试存储结构
    • 1.1线性表链式存储结构定义
    • 1.2头指针与头结点的异同
    • 1.3线性表链式存储结构代码描述
  • 2.单链表的具体实现:
    • 2.1开辟节点
    • 2.2遍历链表以及开辟新节点
  • 3.接口函数的实现(增删查改)
    • 3.1尾插
    • 3.2头插
    • 3.3尾删
    • 3.4头删
    • 3.5查找
    • 3.6在pos位置之前插入x
    • 3.7在pos位置以后插入x
    • 3.8删除pos位置
    • 3.9删除pos的后一个位置
  • 4.单链表结构与顺序存储结构的优缺点
  • 5.链表完整代码:
    • 5.1 SList.h
    • 5.2 SList.c
    • 5.3 Test.c

1.线性表的联试存储结构

1.1线性表链式存储结构定义

在解释这个思路之前,我们先来谈另一个话题。前几年,有一本书风靡了全世界,它叫《达·芬奇密码》,成为世界上最畅销的小说之一,书的内容集合了侦探、惊使和阴谋论等多种风格,很好看。这本书和绝大部分负小说一样,都是同一种处理办法。那就是,作者不会让你事先知道整个过程的全部,而是在一步一步地到这某个环节,才根据现场的信息,获得或推断出下一步是什么,也就是说,每一步除了对你侦破的信息进一步确认外(之前信息也不一定都是对的,有时是证明某个信息不正确),还有就是对下一步如何操作或行动的指引。

不过,这个例子也不完全与线性表相符合,因为案件侦破的线案可能是错综复杂的,有点像我们之后要讲到的树和图的数据结构。今天,我们要讲的是单线索,无分支的情况。即线性表的链式存储结构。

线性表的链式存储结构的特点是用一组任意的存储单元存储线性表的数据元素,这组存储单元可以是连续的,也可以是不连续的。这就意 味着,这些数据元素可以存在内存未被占用的任意位置
(如下图所示)。
图1

以前在顺序结构中,每个数据元素只需要存储数据 元素信息就可以了。现在链式结构中,除了要存储数据 元素信息外,还要存储它的后继元素的存储地址。

因此,为了表示每个数据元素ai与其直接后继数据 元素ai+1(i是下标)之间的逻辑关系,对数据元素ai来说,除了存储 其本身的信息之外,还需存储一个指示其直接后继的信息(即直接后继的存储位置)。我们把存储数据元素信息的域称为数据域,把存储直接后继位置的域称为指针域。指针域中存储的信息称作指针。这两部分信息组成数据元素ai的存储映像,称为结点(Node)。

n个结点(a的存储映像)链结成一个链表,即为线性表(a,ay·,a)的链式存储结构,因为此链表的每个结点中只包含一个指针域,所以叫做单链表。单链表正是通过每个结点的指针域将线性表的数据元素按其逻辑次序链接在一起。

对于线性表来说,总得有个头有个尾,链表也不例外。我们把链表中第一个结点的存储位置叫做头指针,那么整个链表的存取就必须是从头指针开始进行了。之后的每一个结点,其实就是上一个的后继指针指向的位置。想象一下,最后一个结点,它的指针指向哪里?

最后一个,当然就意味着直接后继不存在了,所以我们规定,线性链表的最后一个结点指针为“空”(通常用NULL或“^”符号表示,如下图所示)。
在这里插入图片描述

有时,我们为了更加方便地对链表进行操作,会在单链表的第一个结点前附设一个结点,称为头结点。头结点的数据域可以不存储任何信息,谁叫它是第一个呢,有这个特权。也可以存储如线性表的长度等附加信息,头结点的指针域存储指向第一个结点的指针,如下图所示。
在这里插入图片描述

1.2头指针与头结点的异同

头指针与头结点的异同点,如下图所示:
在这里插入图片描述

1.3线性表链式存储结构代码描述

若线性表为空,则头结点的指针域为“空”,如下图所示:
在这里插入图片描述

这里我们大概用图示表达了内存中单链表的存储状态。看着满图的省略号“…”,就知道是有多么不方便。而我们真正关心的它在内存中的实际位置吗?不是的。这只是它所表示的线性表中的数据元素及数据元素之间色逻辑关系。所以我们改用更方便的存储示意图来表示单链表,如下图所示:
在这里插入图片描述

若带有头结点的单链表,则如下图所示:
在这里插入图片描述

空链表如下图所示:
在这里插入图片描述

单链表中,我们在c语言中可用结构指针来描述:

//线性表的单链表的存储结构:
typedef struct Node
{
  ElemType data;
  struct Node*next;
}Node;
typedef struct Node*LinkList;//定义linkList

从这个结构定义中,我们也就知道,结点由存放数据元素的数据域和存放后继结点地址的指针域组成。假设p是指向线性表第i个元素的指针,则该结点ai 的数据域我们可以用p->data来表示,p->data的值是一个数据元素,结点ai的指针域可以用p->next来表示,p->next的值是一个指针。p->next指向谁呢?当然是指向第i+1个元素,即指向ai+l的指针。也就是说,如果p->data等于a,那么p>next->data等于ai+1(如下图所示)。在这里插入图片描述

2.单链表的具体实现:

2.1开辟节点

首先创建一个新项目,分为三个模块:SList.c用来实现接口函数;SList.h用来结构体创建与函数声明;test.c则用来进行测试我们的接口函数。
在这里插入图片描述

创建节点如下:

在这里插入图片描述

2.2遍历链表以及开辟新节点

咱们首先用一个cur来存放头结点的地址;

在这里插入图片描述

那后面节点的数据怎么访问呢?咱们可以让cur->next赋给cur;

在这里插入图片描述

依次内推;当cur为空时;说明已经访问结束。 最后打印即可。

在这里插入图片描述

为方便测试我们可以先写一个交互性的链表测试:

在这里插入图片描述

写交互性测试的时候,会涉及到开辟新节点,这里我们可以抽离一个函数来专门进行开辟新节点。

在这里插入图片描述
测试结果如下:
在这里插入图片描述

3.接口函数的实现(增删查改)

3.1尾插

那么如何实现尾插呢?尾插我们首先得先找到尾。
那么如何找呢?

先看下面这个代码。

在这里插入图片描述
如果要是这样找尾的话,就会出现一个问题。我们画图分析一下。

这个代码是不是首先有三个指针变量 plist tail newnode;

在这里插入图片描述随着代码运行,最后taill的地址为空,假设新节点的地址为0x0012ff00,那节点newnode存放的地址也就是0x0012ff00,最后呢,又把newnode的地址给了taill,看起来没问题,但有没有想过,这三个指针变量出了作用域呢?
在这里插入图片描述
出了作用域,这三个指针变量是不是都销毁了,这不仅造成了内存泄漏还没有吧链表链接起来。基于这个问题,我们在回过来思考这个问题,如何找尾?

在这里插入图片描述
所以我们的尾用taii找的时候,条件不是null结束,而是存放null前一个的地址。

继续思考一下,我们写完了吗?那如果本身就是个空链表呢?也就是说空链表传过来的时候。第一次尾插怎么插呢?看下面这个代码。

在这里插入图片描述
这个代码就会有一个明显的错误,插入不进去。为什么会这样呢?
phead=newnode这一步,这一步是把0x0012ffcc给了phead,出了作用域,phead,newnode****销毁,那么显然我们的plist的地址并没有发生任何变化,所以插入不进去。

这就是典型的形参与实参之间的区别,形参只是实参的一份临时拷贝。那么怎们样才能改变呢,那就需要传地址了。

在这里插入图片描述
经过以上的不断修改,最终尾插的接口函数完整代码如下:
在这里插入图片描述

测试结果如下:

在这里插入图片描述

总结一下:

在这里插入图片描述

3.2头插

有了尾插的思想,头插就简单了。
在这里插入图片描述
实质也就是修改plist,所以还是传值还是用二级指针。

完整代码如下:

在这里插入图片描述

测试结果如下:

在这里插入图片描述

3.3尾删

如果是空链表,我们可以直接使用断言。

在这里插入图片描述

一个节点直接释放掉plist.两个节点以上就首先需要找尾,先看下面这个代码。(**pphead就是plist)

在这里插入图片描述

上面这个代码找到尾后,直接把taill置空,肯定不行

在这里插入图片描述

free(taill)的本质是把tail指向的节点给free了,再把taill置空。出了作用域,taill销毁,那他前一个还是空。所以还需要找到taill的前一个。

以下两种解决办法都可以。

在这里插入图片描述
最终完整代码如下:
在这里插入图片描述

测试结果如下:

在这里插入图片描述

删除6个。
在这里插入图片描述

3.4头删

同理,头删与尾删大同小异,头删实现更简单。
在这里插入图片描述

测试结果如下:

在这里插入图片描述

3.5查找

查找实质还是遍历链表:

在这里插入图片描述

3.6在pos位置之前插入x

pos是任意一个节点,防止为空呢,我们先检查一下:
在这里插入图片描述

那他还有什么特殊情况呢,头插,尾插就是其中两种,其次处理pos在中间位置。

在这里插入图片描述

完整代码如下:

在这里插入图片描述

测试结果如下:在给定数字前面插它的十倍

在这里插入图片描述

3.7在pos位置以后插入x

要是后插就会便捷很多。因为他不可能实现头插,所以就会很简单。

在这里插入图片描述

如果是第一个代码:测试结果如下:
在这里插入图片描述
进入了死循环。

修改后完整代码如下:

在这里插入图片描述

测试结果如下:
在这里插入图片描述

3.8删除pos位置

删除部分就简单了。分情况,头删首先需要单独处理,其次尾删是不需要单独处理的,因为正常删就已经包含尾删情况了。

在这里插入图片描述

完整代码如下:

在这里插入图片描述

测试结果如下:

在这里插入图片描述

3.9删除pos的后一个位置

删后一个考虑的就是要找到前一个,处理好这个就简单了。其次有个坑,它删不了头。

在这里插入图片描述

完整代码:
在这里插入图片描述

4.单链表结构与顺序存储结构的优缺点

简单地对单链表结构和顺序存储结构做对比:

在这里插入图片描述
通过上面的对比,我们可以得出一些经验性的结论:

1.若线性表需要频繁查找,很少进行插入和删除操作时,宜采用顺序存储结构。若需要频繁插入和删除时,宜采用单链表结构。比如说游戏开发中,对于用户注册的个人信息,除了注册时插入数据外,绝大多数情况都是读取,所以应该考虑用顺序存储结构。而游戏中的玩家的武器或者装备列表,随着玩家的游戏过程中,可能会随时增加或删除,此时再用顺序存储就不太合适了,单链表结构就可以大展拳脚。当然,这只是简单的类比,现实中的软件开发,要考虑的问题会复杂得多。

2.当线性表中的元素个数变化较大或者根本不知道有多大时,最好用单链表给构。这样可以不需要考虑存储空间的大小问题。而如果事先知道线性表的大致长度,比如一年12个月,一周就是星期一至星期日共七天,这种用顺序存储结构效率会高很多。

总之,线性表的顺序存储结构和单链表结构各有其优缺点,不能简单地说哪个好,哪个不好,需要根据实际情况,来综合平衡采用哪种数据结构更能满足和达到需求和性能。

5.链表完整代码:

5.1 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);
SLTNode* BuySListNode(SLTDataType x);

//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x);
//头插
void SLTPushFront(SLTNode** pphead, SLTDataType x);
//尾删
void SLTPopBack(SLTNode** pphead);
//头删
void SLTPopFront(SLTNode** pphead);
//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x);
//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x);
//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x);
//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos);
//删除pos的后一个位置
void SLTEraseAfter(SLTNode* pos);

5.2 SList.c

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"

//打印函数
void SLTPrint(SLTNode* phead)
{
	SLTNode* cur = phead;
	//while (cur != NULL)
	while (cur)
	{
		printf("%d->", cur->data);
		cur = cur->next;
	}
	printf("NULL\n");
}

//开辟新节点
SLTNode* BuySListNode(SLTDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	if (newnode == NULL)
	{
		perror("malloc fail");
		exit(-1);
	}

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

	return newnode;
}


//尾插
void SLTPushBack(SLTNode** pphead, SLTDataType x)
{
	SLTNode* newnode = BuySListNode(x);
	if (*pphead == NULL)
	{
		//改变的结构体的指针
		*pphead = newnode;
	}
	else
	{
		SLTNode* tail = *pphead;
		while (tail->next != NULL)
		{
			tail = tail->next;
		}

		//改变的结构体
		tail->next = newnode;
	}
}


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

//尾删
void SLTPopBack(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;


		/*SLTNode* tailprev = NULL;
		SLTNode* tail = *pphead;
		while (tail->next)
		{
			tailprev = tail;
			tail = tail->next;
		}

		free(tail);
		tail = NULL;
		tailprev->next = NULL;*/
	}
}

//头删
void SLTPopFront(SLTNode** pphead)
{

	//空
	assert(*pphead);

	//非空
	SLTNode* newnode = (*pphead)->next;
	free(*pphead);
	*pphead = newnode;
}

//查找
SLTNode* SLTFind(SLTNode* phead, SLTDataType x)
{
	SLTNode* cur = phead;
	while (cur)
	{
		if (cur->data == x)
		{
			return cur;
		}
		cur = cur->next;
	}
	return NULL;

}


//在pos位置之前插入x
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLTDataType x)
{
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLTPushFront(pphead, x);

	}
	else
	{
		SLTNode* prev = *pphead;
		while (prev->next != pos)
		{
			prev = prev->next;
		}

		SLTNode* newnode = BuySListNode(x);
		prev->next = newnode;
		newnode->next = pos;
	}
}

//在pos位置以后插入x
void SLTInsertAfter(SLTNode* pos, SLTDataType x)
{
	assert(pos);

	SLTNode* newnode = BuySListNode(x);
	/*pos->next = newnode;*/
	newnode->next = pos->next;
	pos->next = newnode;
}

//删除pos位置
void SLTErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(pos);

	if (pos == *pphead)
	{
		SLTPopFront(pphead);
	}
	else
	{
		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是否为尾节点
	assert(pos->next);

	SLTNode* posNext = pos->next;

	pos->next = posNext = posNext->next;

	free(posNext);

	posNext = NULL;
}

5.3 Test.c

#define _CRT_SECURE_NO_WARNINGS
#include"SList.h"

//交互链表测试
void TestSList1()
{
	int n;
	printf("请输入链表的长度:\n");
	scanf("%d", &n);
	printf("请依次输入每个节点的值:\n");
	SLTNode* plist = NULL;
	for (size_t i = 0; i < n; i++)
	{
		int val;
		scanf("%d", &val);
		SLTNode* newnode = BuySListNode(val);

		//头插
		newnode->next = plist;
		plist = newnode;
	}
	SLTPrint(plist);

}



//测试尾插头插
void TestSList2()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);


	SLTPushFront(&plist, 10);
	SLTPushFront(&plist, 20);
	SLTPushFront(&plist, 30);
	SLTPushFront(&plist, 40);
	SLTPrint(plist);

}

//测试尾删
void TestSList3()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);


	SLTPopBack(&plist);
	SLTPrint(plist);


	SLTPopBack(&plist);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);

	SLTPopBack(&plist);
	SLTPrint(plist);

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

}

//测试头删
void TestSList4()
{
	SLTNode* plist = NULL;
	SLTPushBack(&plist, 1);
	SLTPushBack(&plist, 2);
	SLTPushBack(&plist, 3);
	SLTPushBack(&plist, 4);
	SLTPushBack(&plist, 5);
	SLTPrint(plist);


	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	SLTPopFront(&plist);
	SLTPrint(plist);

	/*SLTPopFromt(&plist);
	SLTPrint(plist);*/
}

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


	SLTNode* pos = SLTFind(plist, 40);
	if (pos)
	{
		pos->data *= 10;
	}
	SLTPrint(plist);

	int x;
	scanf("%d", &x);
	pos = SLTFind(plist, x);
	if (pos)
	{
		SLTInsert(&plist, pos, x * 10);

	}
	SLTPrint(plist);

}


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

	int x;
	scanf("%d", &x);
	SLTNode* pos = SLTFind(plist, x);
	if (pos)
	{
		SLTErase(&plist, pos);
	}
	SLTPrint(plist);
}



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

	int x;
	scanf("%d", &x);
	SLTNode* pos = SLTFind(plist, x);
	if (pos)
	{
		SLTEraseAfter(pos);
		pos = NULL;
	}
	SLTPrint(plist);


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


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


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

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

}

int main()
{

	TestSList7();
}

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

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

相关文章

2023年03月 C/C++(四级)真题解析#中国电子学会#全国青少年软件编程等级考试

第1题&#xff1a;最佳路径 如下所示的由正整数数字构成的三角形: 7 3 8 8 1 0 2 7 4 4 4 5 2 6 5 从三角形的顶部到底部有很多条不同的路径。对于每条路径&#xff0c;把路径上面的数加起来可以得到一个和&#xff0c;和最大的路径称为最佳路径。你的任务就是求出最佳路径上的…

天正(建筑、暖通、给排水、电气、结构)软件安装包分享(附安装教程)

目录 一、软件简介 二、软件下载 一、软件简介 天正软件是一款由天正集团开发的建筑工程设计软件&#xff0c;广泛应用于建筑设计领域。该软件旨在提供便捷、高效的建筑设计工具&#xff0c;帮助设计师快速创建高质量的建筑图纸。 以下是天正软件的主要特点&#xff1a; 支…

Spring注解之@validated的使用

使用步骤 1.引入依赖 <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-validation</artifactId> </dependency> 2.异常拦截类 /*** 全局异常处理*/ Slf…

二级MySQL(九)——表格数据处理练习

在Mysql中&#xff0c;可以用INSERT或【REPLACE】语句&#xff0c;向数据库中已一个已有的表中插入一行或多行记录。 在Mysql中&#xff0c;可以用【DELETE】或【TRUNCATE】语句删除表中的所有记录。 在Mysql中&#xff0c;可以用【UPDATE】语句来修改数据表中的记录。 为了完…

齐套检查与分配在生产计划中的实现

最近一段时间看到很多关于生产计划中&#xff0c;作齐套检查与分析讨论&#xff0c;正好我们的易排1.5版添加了类似功能。本文结合易排平台上相应的功能与特征&#xff0c;介绍一下我们在这方面的些许研究结论与看法。 本文中用到些引用自易排平台的概念&#xff0c;先行给出定…

React笔记(一)初识React

一、React概述 1、什么是react react的官网:React 用于构建用户界面的 JavaScript 库&#xff0c;它也是一个渐进式的用于构建用户界面的javascript框架 2、主要特征 声明式&#xff1a;使用原生JS编写的页面存在着开发效率低下、性能较差的情况&#xff0c;使用react大家就…

JavaWeb 速通JQuery

目录 一、JQuery快速入门 1.基本介绍 : 2.入门案例 : 二、JQuery对象 1.基本介绍 : 2.DOM对象 --> JQuery对象 : 3.JQuery对象 --> DOM对象 : 三、JQuery选择器 1.简介 : 2.基本选择器 : 3.层次选择器 : 4.过滤选择器 : 4.1 基础过滤选择器 4.2 内容过滤选择…

wget方式下载DAAC数据

1. 注册DAAC账号 2. 申请数据&#xff0c;获得含下载链接的txt文件 3. 下载配置wget 4.下载&#xff1a; 4.1 创建目录用来保存数据&#xff08;如 E:\3CMB&#xff09; 4.2 在新创建目录下 创建文件 cookies.txt文件 4.3 将含下载链接的txt文件移动到新创建的文件夹中 …

老胡的周刊(第105期)

老胡的信息周刊[1]&#xff0c;记录这周我看到的有价值的信息&#xff0c;主要针对计算机领域&#xff0c;内容主题极大程度被我个人喜好主导。这个项目核心目的在于记录让自己有印象的信息做一个留存以及共享。 &#x1f3af; 项目 Piwigo[2] Piwigo 是一个开源的网络照片库软…

01 java 学习 数据类型、基础语法、封装、继承、多态、接口、泛型、异常等

目录 环境搭建和基础知识 什么是JRE: 什么是JDK: 基础数据类型 分支选择if else switch和c一毛一样 for和while循环还有数组基本和c一样 封装 函数调用、传参、命名规范、数组新命名规范 java输入Scanner scanner new Scanner(System.in); 类的创建和使用以及封装修饰符…

【马拉车算法/动态规划】最长回文字串

最长回文字串 1.问题描述2.中心扩展法&#xff08;O(N^2)&#xff09;3.动态规划4.Manacher(马拉车算法) 1.问题描述 常用有3种算法&#xff1a;中心扩展法、动态规划和Manacher算法 2.中心扩展法&#xff08;O(N^2)&#xff09; 解释&#xff1a; 从中心向外扩展。 分为两种…

Please use ‘App‘ component instead.报错问题解决

今天我在用 antd 组件库编写项目发生了如下报错 这个警告是关于 antd 组件库中的一个问题&#xff0c;提示在静态函数中无法像动态主题一样使用上下文&#xff08;context&#xff09;。建议使用 App 组件来解决此问题。 具体解决方法如下&#xff1a; 确保你的应用程序包含一…

深入解析Java中的位运算符:<<、>>和>>>

当谈到位运算符时&#xff0c;Java中的<<、>>和>>>运算符在源码中无疑是经常出现的。这些运算符在处理整数类型的数据时发挥着重要作用。它们主要用于对二进制位进行操作&#xff0c;是一种高效处理位级信息的方式。让我们深入探讨一下这些运算符的工作原…

数据库的类型

一说到数据库&#xff0c;大多数人可能像我一样&#xff0c;首先想到的就是 MySQL、Oracle 这样的关系型数据库。因为我们平时接触的最多&#xff0c;而且大学课程中有关于数据库的&#xff0c;也是以关系型数据库为主的。 其实&#xff0c;除了关系型数据库外&#xff0c;还有…

八大排序算法 (python版本)

八大排序算法 个人学习笔记 如有问题欢迎指正交流快速排序经常考&#xff0c; 如果只掌握一个排序算法的话&#xff0c;首选快速排序算法 八大排序算法通常指的是以下八种经典排序算法&#xff1a; 1. 冒泡排序 (Bubble Sort) 使用场景&#xff1a;适用于小规模数据的排序&a…

openCV实战-系列教程9:傅里叶变换(傅里叶概述/频域变换结果/低通与高通滤波)、原理解析、源码解读

OpenCV实战系列总目录 打印图像直接用这个函数&#xff1a; def cv_show(img,name):cv2.imshow(name,img)cv2.waitKey()cv2.destroyAllWindows()1、傅里叶变换 在生活中&#xff0c;我们的大部分事情都是以时间为参照的&#xff0c;用时间为参照的为时域分析&#xff0c;在频…

【C语言基础】数据输入输出

&#x1f4e2;&#xff1a;如果你也对机器人、人工智能感兴趣&#xff0c;看来我们志同道合✨ &#x1f4e2;&#xff1a;不妨浏览一下我的博客主页【https://blog.csdn.net/weixin_51244852】 &#x1f4e2;&#xff1a;文章若有幸对你有帮助&#xff0c;可点赞 &#x1f44d;…

视觉语言多模态预训练综述

论文: https://arxiv.org/pdf/2207.01772 预训练数据集 预训练任务 模型结构 本文根据特征在进行视觉和语言模态融合处理之前是否进行处理,将VLP 模型按结构分为单流式(single-stream) 和双流式( cross-stream) 单流模型将视觉特征和语言特征直接输入融合模块,进行模型训练,…

【小沐学Unity3d】3ds Max 骨骼动画制作(Physique 修改器)

文章目录 1、简介2、Physique 工作流程3、Physique 对象类型4、Physique 增加骨骼5、Physique 应用和初始化6、Physique 顶点子对象7、Physique 封套子对象8、设置关键点和自动关键点模式的区别8.1 自动关键点8.2 设置关键点 结语 1、简介 官方网址&#xff1a; https://help.…

Nacos 注册中心的使用(单体)

环境 springboot springcloud Nacos注册中心服务端 下载windows版或Linux版&#xff1a;https://nacos.io/zh-cn 目录结构&#xff1a; 配置文件./config/application.properties 启动文件./bin/startup.cmd&#xff1a; cmd命令启动单机服务startup.cmd -m standalone 父…