数据结构:线性表————单链表专题

 🌈个人主页:小新_-

🎈个人座右铭:“成功者不是从不失败的人,而是从不放弃的人!”🎈

🎁欢迎各位→点赞👍 + 收藏⭐️ + 留言📝

🏆所属专栏: 数据结构与算法欢迎订阅,持续更新中~~~

                      

         ✨让小新带着你快乐的学习吧~✨

目录

1. 链表的概念及结构

2、单链表的实现

准备工作

1、单链表的插入

1)头插

2)尾插

3)指定位置前插

4)指定位置后插

2、单链表的删除

1)头删

2)尾删

3)删除指定位置节点

4)删除指定位置之后节点

3、单链表的查找

4、单链表的销毁

3、链表的分类

4、 链表经典算法OJ题⽬

3.1 单链表相关经典算法OJ题1:移除链表元素(点击进入题目)

3.2 单链表相关经典算法OJ题2:反转链表(点击进入题目)

3.3 单链表相关经典算法OJ题3:合并两个有序链表(点击进入题目)

3.4 单链表相关经典算法OJ题4:链表的中间结点(点击进入题目)

3.5 循环链表经典应⽤-环形链表的约瑟夫问题(点击进入题目)

3.6 单链表相关经典算法OJ题5:分割链表(点击进入题目)


1. 链表的概念及结构

概念:链表是⼀种物理存储结构上⾮连续、⾮顺序的存储结构,数据元素的逻辑顺序是通过链表
中的指针链接次序实现的 。
链表的结构跟⽕⻋⻋厢相似,淡季时⻋次的⻋厢会相应减少,旺季时⻋次的⻋厢会额外增加⼏节。只 需要将⽕⻋⾥的某节⻋厢去掉/加上,不会影响其他⻋厢,每节⻋厢都是独⽴存在的。
⻋厢是独⽴存在的,且每节⻋厢都有⻋⻔。想象⼀下这样的场景,假设每节⻋厢的⻋⻔都是锁上的状 态,需要不同的钥匙才能解锁,每次只能携带⼀把钥匙的情况下如何从⻋头⾛到⻋尾?
最简单的做法:每节⻋厢⾥都放⼀把下⼀节⻋厢的钥匙。
在链表⾥,每节“⻋厢”是什么样的呢?
与顺序表不同的是,链表⾥的每节"⻋厢"都是独⽴申请下来的空间,我们称之为“结点/节点”
节点的组成主要有两个部分:当前节点要保存的数据和保存下⼀个节点的地址(指针变量)。
图中指针变量 plist保存的是第⼀个节点的地址,我们称plist此时“指向”第⼀个节点,如果我们希
望plist“指向”第⼆个节点时,只需要修改plist保存的内容为0x0012FFA0。
为什么还需要指针变量来保存下⼀个节点的位置?
链表中每个节点都是独⽴申请的(即需要插⼊数据时才去申请⼀块节点的空间),我们需要通过指针 变量来保存下⼀个节点位置才能从当前节点找到下⼀个节点。
结合前⾯学到的结构体知识,我们可以给出每个节点对应的结构体代码:
struct SListNode
{
 int data; //节点数据
 struct SListNode* next; //指针变量⽤保存下⼀个节点的地址
};
当我们想要保存⼀个整型数据时,实际是向操作系统申请了⼀块内存,这个内存不仅要保存整型数
据,也需要保存下⼀个节点的地址(当下⼀个节点为空时保存的地址为空)。
当我们想要从第⼀个节点⾛到最后⼀个节点时,只需要在前⼀个节点拿上下⼀个节点的地址(下⼀个 节点的钥匙)就可以了。
补充说明:
1、链式机构在逻辑上是连续的,在物理结构上不⼀定连续
2、节点⼀般是从堆上申请的
3、从堆上申请来的空间,是按照⼀定策略分配出来的,每次申请的空间可能连续,可能不连续

2、单链表的实现

准备工作

单链表实现前,有几个小段代码和问题

1、首先,我们来搞懂一个一个概念上的问题,就是节点的实参形参问题,其实就是考验对指针的理解与掌握

2、申请新的节点

代码比较简单,用malloc函数申请新节点的空间,让新节点的的data域置为x,next域为空

SLTNode* SLNewNode(SLDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->Data = x;
	newnode->next = NULL;
	return newnode;
}

3、打印当前链表

上代码

void SLPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->Data);
		pcur = pcur->next;
	}
	printf("NULL");
}

4、单链表的声明

typedef int SLDataType;
typedef struct SListNode
{
	SLDataType Data;
	struct SListNode* next;
}SLTNode;

1、单链表的插入

1)头插

分析:

尾删思路比较简单,我们有头结点的指针phead,我们让我们新申请的节点的next指针,指向原来的头结点,就完成了,我们考虑一下特殊情况,如果链表为空,怎么办?那还不简单,直接成为新的节点,代码就跟不是空表一样,so easy!小小头插,拿下拿下。

void SLPushFront(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLNewNode(x);
	newnode->next = *pphead;
	*pphead = newnode;


}

2)尾插

分析:

如图,我们想插入一个元素4,如何插入呢?首先,我们得找到原尾节点吧。然后让原尾节点的next指针指向4这个新节点,这样我们的4就成为了尾节点,再让4的next指针指向NULL。但有一个问题,那就是如果链表为空怎么办?那就没有尾节点了。直接将这个节点作为我们的新节点。所以,大体思路就是,先判断链表是否为空,如果是就直接作为新的节点,如果不是,我们就先找到尾节点,然后执行插入操作就可以了。

代码如下:

void SLPushBack(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLNewNode(x);
	//链表为空,作为结点
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	//链表不为空,寻找尾节点
	SLTNode* ptail = *pphead;//寻找尾节点
	while (ptail->next)
	{
		ptail = ptail->next;
	}
	//ptail就是尾节点
	ptail = newnode;
}

3)指定位置前插

分析:

我们看到,要想在pos(3)之前插入,我们就要找到pos之前的节点prev,prev的next指向newnode,newnode的next指向pos。考虑特殊情况,当pos是头结点时,就没有prev,怎么办呢?我们可以直接调用头插即可。

代码如下:

void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	SLTNode* newnode=  SLNewNode(x);
	//如果pos是头结点
	if (pos == *pphead)
	{
		SLPushFront(newnode, x);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = newnode;
	newnode->next = pos;
}

4)指定位置后插

分析:

指定位置后插比指定位置前插较为简单,但要注意的是顺序,如果先把pos的next给newnode,newnode中的next保存的是pos的下一个节点地址,然后再将newnode的next指向下一节点,这样导致pos的next不再指向真正的下一节点。而应该先把pos的next赋值给newnode的next,再将pos的next指向newnode.

代码如下:

2、单链表的删除

1)头删

分析:

头删比较简单,将原来的第二个节点作为新链表的第一个节点,并将原来第一个节点释放掉,并将next赋给pphead

代码如下:

void SLPopFront(SLTNode** pphead)//头删
{
	assert(pphead);//链表不为空
	assert(*pphead);//->指向第一个节点的地址
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	(*pphead) = next;
}

2)尾删

分析:

既然要进行删除操作,那么链表至少得有一个节点吧,所以得提前判断一下。要进行尾删,首先,我们要找到尾节点的前一个节点,我们就叫他prev吧,让prv不再指向尾节点的next域,而是NULL,然后将尾节点用free函数将尾节点的内存还给操作系统。但只有一个节点的时候呢?我们只能将该节点释放掉咯(没办法的事,无奈)

void SLPopBack(SLTNode** pphead)
{
	assert(pphead);//链表不为空
	assert(*pphead);//->指向第一个节点的地址
	while ((*pphead)->next==NULL)//如果只有一个节点
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	//具有多个节点
	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;
	while (ptail->next)
	{
		prev = ptail;
		ptail=ptail->next;
	}//找到prev了
	prev->next = NULL;
	free(ptail);
ptail=NULL//别忘了置空,以免疯狗乱咬人(狗头 狗头)
}

3)删除指定位置节点

分析:

删除指定位置的节点,我们定义一个指针prev,让prev找到pos之前的节点(寻找prev的循环条件:prev->next !=pos),此时,将prev的next指针指向pos的下一个节点,再将pos释放掉。注意,顺序不能颠倒!!!需要注意的是特殊情况,当pos就是头结点。此时没有prev,我们可以直接执行头删操作。

代码如下:

void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SLPopFront(pphead);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	(prev->next) = (pos->next);
	free(pos);
	pos = NULL;
}

4)删除指定位置之后节点

分析:

思路比较清晰,看图一目了然,将pos的next指针指向pos下一个节点的下一个节点

代码如下:

void SLEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	pos->next = pos->next->next;
	free(pos->next);
	pos->next = NULL;
}

3、单链表的查找

没什么好说的,上代码

SLTNode* SLTFind(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	//遍历链表
	SLTNode* pcur = *pphead;
	while (pcur) //等价于pcur != NULL
	{
		if (pcur->Data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}

4、单链表的销毁

上代码

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

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

完整代码如下

sqlist.c

#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include"SList.h"

void SLPrint(SLTNode* phead)
{
	SLTNode* pcur = phead;
	while (pcur)
	{
		printf("%d->", pcur->Data);
		pcur = pcur->next;
	}
	printf("NULL\n");
}
SLTNode* SLNewNode(SLDataType x)
{
	SLTNode* newnode = (SLTNode*)malloc(sizeof(SLTNode));
	newnode->Data = x;
	newnode->next = NULL;
	return newnode;
}
void SLPushBack(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLNewNode(x);
	//链表为空,作为结点
	if (*pphead == NULL)
	{
		*pphead = newnode;
		return;
	}
	//链表不为空,寻找尾节点
	SLTNode* ptail = *pphead;
	while (ptail->next)
	{
		ptail = ptail->next;
	}
	//ptail就是尾节点
	ptail = newnode;
}
void SLPushFront(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	SLTNode* newnode = SLNewNode(x);
	newnode->next = *pphead;
	*pphead = newnode;
}
void SLPopBack(SLTNode** pphead)
{
	assert(pphead);//链表不为空
	assert(*pphead);//->指向第一个节点的地址
	while ((*pphead)->next==NULL)//如果只有一个节点
	{
		free(*pphead);
		*pphead = NULL;
		return;
	}
	//具有多个节点
	SLTNode* ptail = *pphead;
	SLTNode* prev = NULL;
	while (ptail->next)
	{
		prev = ptail;
		ptail=ptail->next;
	}//找到prev了
	prev->next = NULL;
	free(ptail);
}
void SLPopFront(SLTNode** pphead)//头删
{
	assert(pphead);//链表不为空
	assert(*pphead);//->指向第一个节点的地址
	SLTNode* next = (*pphead)->next;
	free(*pphead);
	(*pphead) = next;
}

//在指定位置之前插入数据
void SLTInsert(SLTNode** pphead, SLTNode* pos, SLDataType x)
{
	assert(pphead);
	assert(pos);
	assert(*pphead);
	SLTNode* newnode=  SLNewNode(x);
	//如果pos是头结点
	if (pos == *pphead)
	{
		SLPushFront(newnode, x);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	prev->next = newnode;
	newnode->next = pos;
}
//在指定位置之后插入数据
void SLInsertAfter(SLTNode* pos, SLDataType x)
{
	assert(pos);
	SLTNode* newnode = SLNewNode(x);
	newnode->next = pos->next;
	pos->next = newnode;
}
//删除pos节点
void SLErase(SLTNode** pphead, SLTNode* pos)
{
	assert(pphead);
	assert(*pphead);
	assert(pos);
	if (pos == *pphead)
	{
		SLPopFront(pphead);
		return;
	}
	SLTNode* prev = *pphead;
	while (prev->next != pos)
	{
		prev = prev->next;
	}
	(prev->next) = (pos->next);
	free(pos);
	pos = NULL;
}
//删除pos之后的节点
void SLEraseAfter(SLTNode* pos)
{
	assert(pos);
	assert(pos->next);
	pos->next = pos->next->next;
	free(pos->next);
	pos->next = NULL;
}
SLTNode* SLTFind(SLTNode** pphead, SLDataType x)
{
	assert(pphead);
	//遍历链表
	SLTNode* pcur = *pphead;
	while (pcur) //等价于pcur != NULL
	{
		if (pcur->Data == x) {
			return pcur;
		}
		pcur = pcur->next;
	}
	//没有找到
	return NULL;
}
//销毁链表
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

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#define _CRT_SECURE_NO_WARNINGS 1
#include<stdio.h>
#include<stdlib.h>
#include<assert.h>
typedef int SLDataType;
typedef struct SListNode
{
	SLDataType Data;
	struct SListNode* next;
}SLTNode;
void SLPrint(SLTNode* phead);
SLTNode* SLNewNode(SLDataType x);
void SLPushBack(SLTNode** phead, SLDataType x);
void SLPushFront(SLTNode** phead, SLDataType x);
void SLPopBack(SLTNode** pphead);
void SLPopFront(SLTNode** pphead);
SLTNode* SLFind(SLTNode** pphead, SLDataType x);

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

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

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

测试文件这里就不包含了,读者朋友可以自己写代码的时候测试

3、链表的分类

链表的结构⾮常多样,以下情况组合起来就有8种(2 x 2 x 2)链表结构:

如下:

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

4、 链表经典算法OJ题⽬

3.1 单链表相关经典算法OJ题1:移除链表元素(点击进入题目)

思路一:遍历原链表,当遇到等于vul节点的时候,就执行删除操作
但有一个问题就是,删除操作太麻烦,有没有别的更好地方法呢?
思路二:创建一个新链表,遍历原链表,当节点值不为val时,尾插到新链表尾部
typedef  struct ListNode ListNode;
struct ListNode* removeElements(struct ListNode* head, int val) {
    //定义新链表的头尾巴指针
    ListNode* newHead,*newTail;
    newHead=newTail=NULL;
    ListNode* pcur=head;
    while(pcur) {
        if(pcur->val !=val)//节点值不为val,插入链表尾部
        {
        if(newHead=NULL)//链表为空
        {
            newHead=newTail=pcur;
        }
        else//链表不为空,插入尾部
        {
            newTail->next=pcur;
            newTail=newTail->next;
        }
        }
        //等于val,直接下一个节点
        pcur=pcur->next;
    }
    if(newTail){
        newTail->next=NULL;
    }
    return newTail;
}

3.2 单链表相关经典算法OJ题2:反转链表(点击进入题目)

思路一:创建一个新链表,遍历原链表,将原链表元素依次头插在新链表当中。

思路二:定义三个指针变量,分别指向,当前节点,前驱和后继节点,改变节点指向即可。

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* reverseList(struct ListNode* head) {
    if(head==NULL){
        return head;
    }
    ListNode* n1,*n2,*n3;
    n1=NULL,n2=head,n3=head->next;
    ListNode* pcur;
    
    while(n2){
        n2->next=n1;
        n1=n2;
        n2=n3;
        if(n3){
        n3=n3->next;
        }

    }
    return n1;
}

3.3 单链表相关经典算法OJ题3:合并两个有序链表(点击进入题目)

思路:建立一个新链表,比较俩个链表元素,谁小就插入新链表
代码:
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */typedef struct ListNode ListNode;
struct ListNode* mergeTwoLists(struct ListNode* list1, struct ListNode* list2) {
    if(list1==NULL){
        return list2;
    }
    if(list2==NULL){
        return list1;
    }
     ListNode* l1,*l2;
    l1=list1,l2=list2;
     ListNode* newHead,*newTail;
    newHead=newTail=(ListNode*)malloc(sizeof(ListNode));

   
    while(l1&&l2){
    if(l1->val<l2->val){
        newTail->next=l1;
        newTail=newTail->next;
        l1=l1->next;
    }
    else{
        newTail->next=l2;
        newTail=newTail->next;
        l2=l2->next;
    }
    }
    if(l1){
        newTail->next=l1;
    }
    if(l2){
        newTail->next=l2;
    }
    ListNode*ret =newHead->next;
    free(newHead);
    newHead=NULL;
    return ret;

}

3.4 单链表相关经典算法OJ题4:链表的中间结点(点击进入题目)

思路一:遍历统计节点个数,当遍历完链表,将节点个数除以2,可以得到中间节点位置
思路二:快慢指针,定义一个快指针和一个慢指针,快指针一次走俩个元素,慢指针一次走一个元素。那当快指针遍历完链表时,慢指针就刚好指向中间节点,输出该节点即可。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */
 typedef struct ListNode ListNode;
struct ListNode* middleNode(struct ListNode* head) {
    ListNode* fast,*slow;
    fast=slow=head;
  
    while(fast&&fast->next){
        fast=fast->next->next;
        slow=slow->next;
        
    }
    return slow;
}

3.5 循环链表经典应⽤-环形链表的约瑟夫问题(点击进入题目)

著名的Josephus问题
据说著名犹太 历史学家 Josephus有过以下的故事:在罗⻢⼈占领乔塔帕特后,39 个犹太⼈与
Josephus及他的朋友躲到⼀个洞中,39个犹太⼈决定宁愿死也不要被⼈抓到,于是决定了⼀个⾃杀 ⽅式,41个⼈排成⼀个圆圈,由第1个⼈开始报数,每报数到第3⼈该⼈就必须⾃杀,然后再由下⼀ 个重新报数,直到所有⼈都⾃杀⾝亡为⽌。
然⽽Josephus 和他的朋友并不想遵从,Josephus要他的朋友先假装遵从,他将朋友与⾃⼰安排在
第16个与第31个位置,于是逃过了这场死亡游戏。
/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){
if(head==NULL){
    return head;
}
ListNode* newHeadLess,*newTailLess,*newHeadGreagter,*newTailGreagter;

newHeadLess=newTailLess=(ListNode*)malloc(sizeof(ListNode));
newHeadGreagter=newTailGreagter=(ListNode*)malloc(sizeof(ListNode));

ListNode* pcur=head;
while(pcur){
    if(pcur->val<x){
        newTailLess->next=pcur;
        newTailLess=newTailLess->next;
    }else{
        newTailGreagter->next=pcur;
        newTailGreagter=newTailGreagter->next;
    }
    pcur=pcur->next;
}
    newTailGreagter->next=NULL;
    newTailLess->next=newHeadGreagter->next;
    ListNode*ret=newHeadLess->next;
    free(newHeadGreagter);
    free(newHeadLess);
    return ret;
}

3.6 单链表相关经典算法OJ题5:分割链表(点击进入题目)

思路:建立大小链表,大于x放大链表,小于x放小链表,最后连接起来

/**
 * Definition for singly-linked list.
 * struct ListNode {
 *     int val;
 *     struct ListNode *next;
 * };
 */

typedef struct ListNode ListNode;
struct ListNode* partition(struct ListNode* head, int x){
if(head==NULL){
    return head;
}
ListNode* newHeadLess,*newTailLess,*newHeadGreagter,*newTailGreagter;

newHeadLess=newTailLess=(ListNode*)malloc(sizeof(ListNode));
newHeadGreagter=newTailGreagter=(ListNode*)malloc(sizeof(ListNode));

ListNode* pcur=head;
while(pcur){
    if(pcur->val<x){
        newTailLess->next=pcur;
        newTailLess=newTailLess->next;
    }else{
        newTailGreagter->next=pcur;
        newTailGreagter=newTailGreagter->next;
    }
    pcur=pcur->next;
}
    newTailGreagter->next=NULL;
    newTailLess->next=newHeadGreagter->next;
    ListNode*ret=newHeadLess->next;
    free(newHeadGreagter);
    free(newHeadLess);
    return ret;
}

 

最后,感谢大家的观看~~

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

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

相关文章

纯小白蓝桥杯备赛笔记--DAY4(数学数据结构图论)

文章目录 数学质因数分解辗转相除法求最大公约数最小公倍数&#xff1a;快速幂乘法逆元费马小定理 逆元乘法逆元素数判定与埃式筛法朴素素数判定法埃式筛法 图论并查集T3:真题--合根植物DijkstraFloyd 基础算法递归&#xff0c;循环&#xff0c;前缀和&#xff0c;差分STL 数学…

数据分析案例(一):地区收入的PCA主成分分析

练习1 地区收入的PCA主成分分析 0.变量说明 1.导包操作 核心思路&#xff1a;导入基础数据操作库包&#xff0c;PCA、k-means 库包&#xff0c;数据可视化库包 import pandas as pd import numpy as np from sklearn.decomposition import PCA from sklearn.preprocessing i…

宝塔面板安装软件 提示需要[xxxMB]内存 强制不能安装

解决方法&#xff1a; 第一步&#xff1a; 编辑修改/www/server/panel/class/下的文件panelPlugin.py vi /www/server/panel/class/panelPlugin.py注释以下判断的内容&#xff1a; ## 第二步&#xff1a; 重启宝塔面板&#xff0c;然后安装即可 bash bt 1

HarmonyOS实战开发-如何实现对游戏实现基本控制。

介绍 本示例基于H5游戏&#xff0c;通过arkui的button实现对游戏实现基本控制&#xff0c;展示webview的JS注入与执行能力&#xff0c;及native应用与H5的通信能力。 本例的H5游戏页面&#xff0c;由https://yangyunhe369.github.io/h5-game-blockBreaker/ 提供 效果预览 使…

三子棋+迷宫

又水了一篇&#xff0c;嘿嘿不废话了&#xff0c;正文开始 文章目录 1.三子棋&#xff08;Tic-Tac-Toe&#xff09;游戏流程解析游戏设计游戏代码实现1. 包含头文件和定义全局变量2. 初始化游戏板3. 打印游戏板4. 玩家行动5. 检查胜利条件6. 主函数下面是完整的C语言代码 2.控…

Codeforces Round 521 (Div. 3)

目录 A. Frog Jumping B. Disturbed People C. Good Array D. Cutting Out E. Thematic Contests F1. Pictures with Kittens (easy version) F2. Pictures with Kittens (hard version) A. Frog Jumping 直接模拟即可注意数据范围需要开long long void solve(){LL a,…

LeetCode-5. 最长回文子串【字符串 动态规划】

LeetCode-5. 最长回文子串【字符串 动态规划】 题目描述&#xff1a;解题思路一&#xff1a;动态规划五部曲解题思路二&#xff1a;动态规划[版本二]解题思路三&#xff1a;0 题目描述&#xff1a; 给你一个字符串 s&#xff0c;找到 s 中最长的回文 子串 。 如果字符串的反序…

kubernetes应用的包管理工具---Helm的安装、部署、构建Helm Chart、分发

kubernetes应用的包管理工具—Helm的安装、部署、构建Helm Chart、分发 文章目录 kubernetes应用的包管理工具---Helm的安装、部署、构建Helm Chart、分发1. 引入Helm的原因1.1 没有使用Helm的部署1.2 使用Helm部署 2. Helm核心概念3. Helm架构3.1 V2版本3.2 V3版本 4. Helm安装…

品牌百度百科词条创建多少钱?

百度百科作为国内最具权威和影响力的知识型平台&#xff0c;吸引了无数品牌和企业争相入驻。一个品牌的百度百科词条&#xff0c;不仅是对品牌形象的一种提升&#xff0c;更是增加品牌曝光度、提高品牌知名度的重要途径。品牌百度百科词条创建多少钱&#xff0c;这成为了许多企…

基于SpringBoot+Vue的高校会议室预定管理系统(源码+文档+部署+讲解)

一.系统概述 伴随着我国社会的发展&#xff0c;人民生活质量日益提高。于是对系统进行规范而严格是十分有必要的&#xff0c;所以许许多多的信息管理系统应运而生。此时单靠人力应对这些事务就显得有些力不从心了。所以本论文将设计一套高校会议室预订管理系统&#xff0c;帮助…

【电控笔记0】拉式转换与转移函数

概要 laplace&#xff1a;单输入单输出&#xff0c;线性系统 laplace 传递函数 总结

python+appium调@pytest.mark.parametrize返回missing 1 required positional argument:

出错描述&#xff1a; 1、在做pythonappium自动化测试时&#xff0c;使用装饰器pytest.mark.parametrize&#xff08;“参数”&#xff0c;[值1&#xff0c;值2&#xff0c;值3]&#xff09;&#xff0c;测试脚本执行返回test_xx() missing 1 required positional argument:“…

Mybatis generate xml 没有被覆盖

添加插件即可 <plugin type"org.mybatis.generator.plugins.UnmergeableXmlMappersPlugin"/>

ssm040安徽新华学院实验中心管理系统的设计与实现+jsp

实验中心管理系统 摘 要 本安徽新华学院实验中心管理系统的设计目标是实现安徽新华学院实验中心的信息化管理&#xff0c;提高管理效率&#xff0c;使得安徽新华学院实验中心管理工作规范化、科学化、高效化。 本文重点阐述了安徽新华学院实验中心管理系统的开发过程&#x…

libcurl 简单实用

LibCurl是一个开源的免费的多协议数据传输开源库&#xff0c;该框架具备跨平台性&#xff0c;开源免费&#xff0c;并提供了包括HTTP、FTP、SMTP、POP3等协议的功能&#xff0c;使用libcurl可以方便地进行网络数据传输操作&#xff0c;如发送HTTP请求、下载文件、发送电子邮件等…

蓝桥杯python速成

总写C&#xff0c;脑子一热&#xff0c;报了个Python&#xff08;有一点想锤死自己&#xff09;&#xff0c;临时抱佛脚了 1.list的插入删除 append extend insert&#xff08;在索引位插入99&#xff09;---忘记用法别慌&#xff0c;用help查询 remove&#xff08;去掉第一个3…

mysql题目2

tj11: select sex,count(sex) from t_athletes group by sex; tj12: select name 姓名,TIMESTAMPDIFF(year,birthday,2024-1-1) 年龄 from t_athletes tj13: SELECT * FROM t_athletesWHERE id NOT IN (SELECT aid FROM t_match WHERE sid IN (SELECT id FROM t_sport WHE…

510天,暴雪竞品迎来大考

北京时间4月10日&#xff0c;暴雪娱乐、微软游戏与网易正式宣布重新达成合作。两则数据值得关注&#xff1a; 一是上午暴雪与网易刚宣布合作&#xff0c;中午《魔兽世界》玩家预约就超过了20W。 截图时间为中午12:48 二是在上午10:24&#xff0c;《炉石传说》官方公众号发布回…

直播视频传输处理技术

流程 在视频直播场景中&#xff0c;从拍摄到手机用户接收的整个过程涉及多个技术环节&#xff1a; 视频采集&#xff1a; 视频源通常来自摄像机或智能手机摄像头&#xff0c;通过捕捉连续的画面生成原始视频信号。 编码压缩&#xff1a; 为了减少数据量以适应网络传输&#x…

一个比 Celery 轻量好用的异步任务工具

文章目录 1、RQ安装2、RQ基本概念2.1、Queue2.2、Job2.3、Worker 3、RQ 高级用法3.1、自定义任务失败处理3.2、任务依赖关系3.3、定时任务 4、RQ web 界面5、查看任务结果6、RQ 与 celery 对比7、总结 Python RQ&#xff08;Redis Queue&#xff09;是一个轻量级的异步任务队列…