嵌入式学习——数据结构(双向无头有环链表、内核链表、栈)——day48

news2024/12/26 20:19:47

1. 约瑟夫环问题——双向无头回环链表

1.1 问题描述

        给定 ( n ) 个人(编号为 ( 1, 2, \ldots, n )),他们围成一个圈。从第一个人开始报数,每报到第 ( k ) 个人时,杀掉这个人,然后从下一个人重新开始报数。重复这个过程,直到所有人都被杀死。约瑟夫环问题是要确定最后一个幸存者的编号。

1.2 实质

        每次删除循环链表中的一个节点,直到链表中仅剩一个节点结束

2. 双向无头循环链表代码

2.1 makefile

OBJ:=a.out
OBJS+=main.c doublelink.c
CCl=gcc

$(OBJ):$(OBJS)
	$(CC) $^ -o $@
.PHONY:
clean:
	rm $(OBJ)
test:
	valgrind --tool=memcheck --leak-check=full ./$(OBJ)

2.2 double.h

#ifndef _DOUBLELINK_H_
#define _DOUBLELINK_H_

typedef struct stu
{
    int id;
    char name[32];
    int score;
}DataType;

typedef struct node
{
    DataType data;
    struct node *ppre;
    struct node *pnext;
}DouNode;

typedef struct list
{
    DouNode *phead;
    int clen;
}DouList;

extern DouList *create_dou_link();
extern int is_empty_dou_link(DouList *plist);
extern void dou_link_for_each(DouList *plist, int dir);
extern int push_head_dou_link(DouList *plist, DataType data);
extern int  push_tail_dou_link(DouList *plist, DataType data);
extern int pop_head_dou_link(DouList *plist);
extern int pop_tail_dou_link(DouList *plist);
extern void loop_dou_link(DouList *plist);
extern DouNode *Joseph_loop(DouList *plist);
extern void dou_link_for_remain(DouList *plist);

#endif

2.3 double.c

#include "doublelink.h"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>

DouList *create_dou_link()//创建标签
{
    DouList *plist = NULL;

    plist = (DouList *)malloc(sizeof(DouList));
    if (NULL == plist)
    {
        perror("fail to malloc");
        return NULL;
    }

    plist->phead = NULL;
    plist->clen = 0;

    return plist;
}

int is_empty_dou_link(DouList *plist)//判断空链表
{
    if (NULL == plist->phead)
    {
        return 1;
    }

    return 0;
}

int push_head_dou_link(DouList *plist, DataType data)//头插
{
    DouNode *pnode = NULL;

    pnode = malloc(sizeof(DouNode));
    if (NULL == pnode)
    {
        perror("fail to malloc");
        return -1;
    }

    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    if (is_empty_dou_link(plist))//空链表直接插
    {
        plist->phead = pnode;
    }
    else
    {
        pnode->pnext = plist->phead;
        plist->phead->ppre = pnode;
        plist->phead = pnode;
    }
    plist->clen++;

    return 0;
}

int push_tail_dou_link(DouList *plist, DataType data)//头插
{
    DouNode *p = NULL;
    DouNode *pnode = NULL;

    pnode = malloc(sizeof(DouNode));
    if (NULL == pnode)
    {
        perror("fail to malloc");
        return -1;
    }
    pnode->data = data;
    pnode->ppre = NULL;
    pnode->pnext = NULL;

    if (is_empty_dou_link(plist))//空链表直接插
    {
        plist->phead = pnode;
    }
    else
    {   
        p = plist->phead;
        while (p->pnext != NULL)
        {
            p = p->pnext;
        }

        p->pnext = pnode;
        pnode->ppre = p;
    }
    plist->clen++;

    return 0;
}

int pop_head_dou_link(DouList *plist)//头删
{
    if (is_empty_dou_link(plist))//空链表直接结束程序
    {
        return -1;
    }

    DouNode *pfree = NULL;
    pfree = plist->phead;

    plist->phead = pfree->pnext;//标签指向第二个节点首地址
    if (plist->phead != NULL)//判断是否空链表
    {
        plist->phead->ppre = NULL;//将第二个节点的ppre变为NULL
    }
    free(pfree);

    plist->clen--;

    return 0;
}
 
int pop_tail_dou_link(DouList *plist)//尾删
{
    if (is_empty_dou_link(plist))//空链表程序结束
    {
        return -1;
    }

    DouNode *pfree = NULL;

    pfree = plist->phead;

    while (pfree->pnext)//指针指向最后一个节点
    {
        pfree = pfree->pnext;
    }

    if (pfree->ppre != NULL)//链表有两个以上节点
    {
        pfree->ppre->pnext = NULL;
    }
    else //链表只有一个节点
    {
        plist->phead = NULL;
    }

    free(pfree);
    plist->clen--;

    return 0;
}

void loop_dou_link(DouList *plist)//将非回环链表改为双向回环链表
{
    DouNode *ptmpnode = NULL;

    ptmpnode = plist->phead;
    while (ptmpnode->pnext != NULL)//将指针移动到末尾节点
    {
        ptmpnode = ptmpnode->pnext;
    }

    ptmpnode->pnext = plist->phead;
    plist->phead->ppre = ptmpnode;
}

void dou_link_for_remain(DouList *plist)//打印约瑟夫回环一次处理后链表中剩下的成员信息
{
    int i = 0;
    DouNode *ptmpnode = plist->phead;

    for (i = 0; i < plist->clen; i++)
    {
        printf("%d  ", ptmpnode->data.id);
        printf("%s  ", ptmpnode->data.name);
        printf("%d\n", ptmpnode->data.score);
        ptmpnode = ptmpnode->pnext;
    }
    printf("=========================\n");
}

DouNode *Joseph_loop(DouList *plist)//约瑟夫回环、实质是删除链表节点直到留下最后一个节点为止
{
    DouNode *pfreenode = NULL;//
    DouNode *ptmpnode = NULL;//指向回环

    ptmpnode = plist->phead;

    while (ptmpnode != ptmpnode->pnext)//判断回环是否只剩下一个节点
    {
        
        pfreenode = ptmpnode;//指向当前所在回环的位置

        pfreenode = pfreenode->pnext->pnext;//回环向后移动两个单位
        pfreenode->ppre->pnext = pfreenode->pnext;
        pfreenode->pnext->ppre = pfreenode->ppre; 

        ptmpnode = pfreenode->pnext;//记录要删除的回环的下一个位置,保证循环的延续
        if (pfreenode == plist->phead)//判断要删除的节点是否是表头后的第一个节点、若是,给表头接入要删除节点的下一个节点
        {
            plist->phead = ptmpnode;
        }

        free(pfreenode);
        plist->clen--;
        dou_link_for_remain(plist);//打印链表中剩下的节点信息
    }

    return ptmpnode;
}

2.4 main.c

#include <stdio.h>
#include <stdlib.h>
#include "doublelink.h"

int main(void)
{
    DataType stus[] = {{1, "doinb", 100},
                        {2, "lwx", 67},
                        {3, "lqs", 99},
                        {4, "tian", 98},
                        {5, "gimgoon", 78},
                        {6, "xinyi", 88},
                        {7, "nuguri", 99},
                        {8, "khan", 77},
                        {9, "bo", 94},
                        {10, "xiaolaohu", 60}
                        };
    DouNode *ptmpnode = NULL;
    int i = 0;

    DouList *plist = create_dou_link();//表头创建
    if (NULL == plist)
    {
        return -1;
    }

    for (i = 0; i < sizeof(stus) / sizeof(stus[0]); i++)//给链表中插入结构体中的所有内容
    {
        push_tail_dou_link(plist, stus[i]);//尾插
    }
    dou_link_for_each(plist, 1);
    dou_link_for_each(plist, 0);

    loop_dou_link(plist);//创建双向回环链表
    
    ptmpnode = Joseph_loop(plist);//约瑟夫回环
    printf("%s\n", ptmpnode->data.name); 

    return 0;
}

2.5  判断单向链表是否有环

        利用快慢指针,慢指针走一步,快指针走两步

        快指针每走一步,判断是否为空或者是否与慢指针相遇,相遇为有环链表

3. 内核链表(有头、双向循环链表)

3.1 定义

        Linux内核链表是一种双向循环链表,它的实现非常简洁而高效,主要通过一些宏和内联函数来操作链表。链表节点的结构定义在头文件 <linux/list.h> 中。

3.1 offsetof宏

        获取结构体某个成员到结构体开头的偏移量

3.2 container_of宏

        通过offsetof偏移量获取结构体的首地址

3. 栈

3.1 定义

        栈(Stack)是一种抽象的数据结构,它遵循后进先出(LIFO, Last In First Out)的原则。也就是说,最后放入栈中的元素最先被取出。

3.2 栈的基本操作

        1. 入栈、压栈:将一个元素放入栈顶。

        2. 出栈、弹栈:从栈顶移除一个元素。

        3. 取栈顶元素:查看栈顶元素但不移除它。

        4. 判断栈是否为空:检查栈中是否有元素。

3.3 分类

        (1)按实现方式分类:栈分为顺序栈和链式栈

        1. 顺序栈

               使用数组实现的栈,数组中的元素按顺序存储。优点是实现简单,访问效率高;缺点是栈的容量固定,扩展不便。 

        2. 链式栈

        使用链表实现的栈,链表的每个节点存储一个栈元素。优点是栈的容量可以动态扩展;缺点是指针操作复杂,访问效率相对较低。

        (2)按用途来分类

        1. 操作系统栈

        用于管理程序执行时的函数调用,保存函数调用的返回地址、本地变量等信息。操作系统栈通常是顺序栈,采用固定大小。

                1. 局部变量

                2. 函数的形参、返回值

                3. 函数调用关系——保护现场、恢复现场

3.4 数据结构中的栈——链式栈

4. 面试考点

        区分满增栈、满减栈、空增栈、空减栈(前提:仅限于顺序栈,数组方式构成的)

4.1 满栈和空栈——判断栈顶所在位置是否存有数据而非整个栈有没有数据

        1. 满栈:栈顶所在位置有数据

                入栈操作流程:先向上移动栈顶指针,再将数据压入栈中

        2. 空栈:栈顶所在位置没有数据

                入栈操作流程:先将数据压入栈顶,再向上移动栈顶指针


 

4.2 增栈和减栈——判断栈的生长方向

        0x1000与0x2000,内存高地址为0x2000,内存低地址为0x1000

        1. 增栈:数据入栈时栈顶指针向内存高地址移动

        2. 减栈:数据入栈时栈顶指针向内存低地址移动

(1) 满增栈

        1. 出栈时:栈顶指针向内存高地址移动,再向栈顶入栈数据,

        2. 出栈时:出栈数据,栈顶指针向内存低地址移动,

(2) 满减栈

(3) 空增栈

        1. 出栈时:先向栈顶入栈数据,栈顶指针向内存高地址移动

        2. 出栈时:栈顶指针向内存低地址移动,出栈数据

(4) 空减栈

5. 数据结构中的栈——链式栈

5.1 代码

(1)makefile

OBJ:=a.out
OBJS+=main.c stack.c
CCl=gcc

$(OBJ):$(OBJS)
	$(CC) $^ -o $@
.PHONY:
clean:
	rm $(OBJ)
test:
	valgrind --tool=memcheck --leak-check=full ./$(OBJ)

注意:在终端输入make test可以测试销毁是否成功以及是否有内存泄漏

(2)stack.h

#ifndef _STACK_H_
#define _STACK_H_

typedef int DataType;

typedef struct stact_node
{
    DataType data;
    struct stact_node *pnext;
}StackNode;

typedef struct Stack
{
    StackNode *ptop;
    int clen;
}StackList;

extern StackList *create_stack();
extern int is_empty_stack(StackList *plist);
extern int push_stack(StackList *plist, DataType data);//入栈头插
extern void stack_for_each(StackList *plist);
extern int pop_stack(StackList *plist, DataType *pdata);//出栈头删
extern void clear_stack(StackList *plist);
extern void destory_stack(StackList *plist);
extern int get_stack_top(StackList *plist, DataType *pdata);

#endif

(3)stack.c

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

StackList *create_stack()
{
    StackList *plist = malloc(sizeof(StackList));
    if (NULL == plist)
    {
        perror("fail to malloc");
        return NULL;
    }
    plist->ptop = NULL;
    plist->clen = 0;
    
    return plist;
}

int is_empty_stack(StackList *plist)
{
    if (NULL == plist->ptop)
    {
        return 1;
    }

    return 0;
}

int push_stack(StackList *plist, DataType data)//入栈头插
{
    StackNode *pnode = malloc(sizeof(StackNode));
    if (NULL == pnode)
    {
        perror("fail to malloc");
        return -1;
    }
    pnode->data = data;
    pnode->pnext = NULL;

    pnode->pnext = plist->ptop;
    plist->ptop = pnode;

    plist->clen++;
    
    return 0;
}

void stack_for_each(StackList *plist)
{
	StackNode *ptmp = plist->ptop;

	while (ptmp != NULL)
	{
		printf("%d ", ptmp->data);
		ptmp = ptmp->pnext;
	}

	printf("\n");
}

int pop_stack(StackList *plist, DataType *pdata)//出栈头删
{
    if (is_empty_stack(plist))
    {
        return -1;
    }

    StackNode *pfree = plist->ptop;

    plist->ptop = pfree->pnext;
    if (pdata != NULL)//传入非空地址,将删除的节点的数据传出
    {
        *pdata = pfree->data;
    }

    free(pfree);
    plist->clen--;

    return 0;
}

void clear_stack(StackList *plist)//清空栈区
{
    while (!is_empty_stack(plist))
    {
        pop_stack(plist, NULL);
    }
}

void destory_stack(StackList *plist)
{
    if (!is_empty_stack(plist))
    {
        clear_stack(plist);
    }
    free(plist);
}

int get_stack_top(StackList *plist, DataType *pdata)//获得栈顶数据
{
    if (is_empty_stack(plist))
    {
        return -1;
    }

    *pdata = plist->ptop->data;

    return 0;
}

(4)main.c

#include <stdio.h>
#include <stdlib.h>
#include "stack.h"

int main(void)
{
    DataType tmpdata = 0;
    DataType data[] = {1, 2, 3, 4, 5};
    StackNode *ptmpnode = NULL;
    int i = 0;
    int ret = 0;

    StackList *plist = create_stack();//创建栈表头
    if (NULL == plist)
    {
        return -1;
    }
    
    for (i = 0; i < sizeof(data) / sizeof(data[0]); i++)//入栈所有数据
    {
        push_stack(plist, data[i]);//入栈头插
    }
    stack_for_each(plist);//遍历打印所有数据

#if 0
    for (i = 0; i < sizeof(data)/sizeof(data[0]); i++)//获取栈顶元素并打印,出栈数据,打印栈中的剩下元素
    {
        printf("======== %d ========", i);
        ret = get_stack_top(plist, &tmpdata);
        if (0 == ret)
        {
            printf("ptop data:%d   ", tmpdata);
        }

        pop_stack(plist, NULL);
        stack_for_each(plist);//遍历打印所有数据
    }
#endif

#if 0
    clear_stack(plist);//清理栈中所有节点
    if (is_empty_stack(plist))
    {
        printf("clear_stack success!\n");
    }
#endif

#if 1
    destory_stack(plist);
#endif

    return 0;
}

5.2  应用

                1. 撤回操作

                2. 浏览器返回上一层操作

                3. 计算器

        示例:利用链式栈实现四则运算

        1. makefile

OBJ:=a.out
OBJS+=calculate.c stack.c
CCl=gcc

$(OBJ):$(OBJS)
	$(CC) $^ -o $@
.PHONY:
clean:
	rm $(OBJ)
test:
	valgrind --tool=memcheck --leak-check=full ./$(OBJ)

        2. calculate.c

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "stack.h"

int is_char_num(char ch)//判断此指针是否指向数字
{
	if (ch >= '0' && ch <= '9')
	{
		return 1;
	}
	return 0;
}

int get_opt_level(char opt)//获得运算符优先级
{
	switch(opt)
	{
		case '+':
		case '-':
			return 1;
        case '*':
        case '/':
			return 2;
	}
}

int get_result(int num1, int num2, char opt)//获得运算结果
{
	switch(opt)
	{
		case '+':return num1 + num2;
		case '-':return num1 - num2;
		case '/':return num1 / num2;
		case '*':return num1 * num2;
	}
}

int main(int argc, const char *argv[])
{
	char press[128] = {0};//运算表达式
	DataType num = 0;//存储每个运算数
	DataType data;
	DataType opt;
	DataType num1;
	DataType num2;
	DataType res = 0;   //计算器返回值

	StackList *pNumStack = create_stack();//存储数字的栈
	StackList *pOptStack = create_stack();//存储运算符的栈

	fgets(press, sizeof(press), stdin);
	press[strlen(press)-1] = '\0';
	
	char *p = press;//遍历运算式字符串
	
	while (1)
	{
		if ('\0' == *p && is_empty_stack(pOptStack))//循环结束的条件,指针遍历到字符串末尾,运算符栈为空
		{
			break;
		}
        
        /*判断条件1*/
		while (is_char_num(*p))//拆解数字
		{
			num = num * 10 + (*p - '0');
			p++;
			if (!is_char_num(*p))
			{
				push_stack(pNumStack, num);//入栈数字
				num = 0;
			}
		}
		
        /*判断条件2*/
		if (is_empty_stack(pOptStack))//运算符栈为空,入栈
		{
			push_stack(pOptStack, *p);
			p++;
			continue;
		}

        /*判断条件3*/
		if ('\0' == *p && !is_empty_stack(pOptStack))//结束条件
		{
			pop_stack(pOptStack, &opt);
			pop_stack(pNumStack, &num2);
			pop_stack(pNumStack, &num1);
			res = get_result(num1, num2, opt);
			push_stack(pNumStack, res);	
			continue;
		}

        /*判断条件4*/
		get_stack_top(pOptStack, &data);
		if (get_opt_level(data) < get_opt_level(*p))//运算符栈不为空,本次运算符优先级大于栈顶中运算符优先级
		{
			push_stack(pOptStack, *p);
			p++;
		}
		else if (get_opt_level(data) >= get_opt_level(*p))
		{
			pop_stack(pOptStack, &opt);
			pop_stack(pNumStack, &num2);
			pop_stack(pNumStack, &num1);
			res = get_result(num1, num2, opt);
			push_stack(pNumStack, res);
		}
	}

	get_stack_top(pNumStack, &res);
	printf("res = %d\n", res);
	
	destaroy_stack(pNumStack);
	destaroy_stack(pOptStack);

	return 0;
}

        3. stack.c

#include "stack.h"
#include <stdlib.h>
#include <stdio.h>

StackList *create_stack()
{
	StackList *pstack = malloc(sizeof(StackList));
	if (NULL == pstack)
	{
		perror("fail malloc");
		return NULL;
	}
	pstack->ptop = NULL;
	pstack->clen = 0;

	return pstack;
}
int is_empty_stack(StackList *pstack)
{
	if (NULL == pstack->ptop)
	{
		return 1;
	}
	return 0;
}
int push_stack(StackList *pstack, DataType data)
{
	StackNode *pnode = malloc(sizeof(StackNode));
	if (NULL == pnode)
	{
		perror("fail malloc");
		return -1;
	}
	pnode->data = data;
	pnode->pnext = NULL;

	pnode->pnext = pstack->ptop;
	pstack->ptop = pnode;

	pstack->clen++;

	return 0;
}
int pop_stack(StackList *pstack, DataType *pdata)
{
	if (is_empty_stack(pstack))
	{
		return 1;
	}
	
	StackNode *pfree = pstack->ptop;
	pstack->ptop = pfree->pnext;
	if (pdata != NULL)
	{
		*pdata = pfree->data;
	}
	free(pfree);
	pstack->clen--;
	
	return 0;
}
void clear_stack(StackList * pstack)
{
	while (!is_empty_stack(pstack))
	{
		pop_stack(pstack, NULL);
	}
}
void destaroy_stack(StackList *pstack)
{
	clear_stack(pstack);
	free(pstack);
}
int get_stack_top(StackList *pstack, DataType *pdata)
{
	if (is_empty_stack(pstack))
	{
		return 1;
	}
	*pdata = pstack->ptop->data;
	return 0;
}

        4. stack.h

#ifndef __STACK_H__
#define __STACK_H__

typedef int DataType;

typedef struct stk_node
{
	DataType data;
	struct stk_node *pnext;
}StackNode;

typedef struct Stack
{
	StackNode *ptop;
	int clen;
}StackList;

StackList *create_stack();
int is_empty_stack(StackList *);
int push_stack(StackList *, DataType );
int pop_stack(StackList *, DataType *);
void clear_stack(StackList *);
void destaroy_stack(StackList *);
int get_stack_top(StackList *, DataType *);

#endif

        

        

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

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

相关文章

一些硬件知识(十二)

1、请说明一下滤波磁珠和滤波电感的区别。 因此磁珠通常用于模数地的连接。 磁珠由导线穿过铁氧体组成&#xff0c;直流电阻很小&#xff0c;在低频时阻抗也很小&#xff0c;对直流信号几乎没有影响。 在高频&#xff08;几十兆赫兹以上&#xff09;时磁珠阻抗比较大&#xff0…

事务处理概述

一、引言 1、决定数据库应用系统性能的DBMS的关键实现技术——事务处理技术 事务处理技术是为了解决早期的DBMS产品在应用过程中遇到的现实问题而在后续的DBMS产品中加以实现的技术 2、比如在银行系统中&#xff0c;账户转账是常见的业务&#xff0c;是金融学中的交易trans…

【MLP-BEV(7)】深度的计算。针孔相机和鱼眼相机对于深度depth的采样一个是均匀采样,一个是最大深度均匀采样

文章目录 1.1 问题提出1.1 看看DD3D 的深度是怎么处理的给出代码示例 1.2 我们看看BEVDepth的代码 1.1 问题提出 针孔相机和鱼眼相机的投影模型和畸变模型不一样&#xff0c;如果对鱼眼的模型不太了解可以到我的这篇博客【鱼眼镜头11】Kannala-Brandt模型和Scaramuzza多项式模…

go语言day4 引入第三方依赖 整型和字符串转换 进制间转换 指针类型 浮点数类型 字符串类型

Golang依赖下载安装失败解决方法_安装go依赖超时怎么解决-CSDN博客 go安装依赖包&#xff08;go get, go module&#xff09;_go 安装依赖-CSDN博客 目录 go语言项目中如何使用第三方依赖&#xff1a;&#xff08;前两步可以忽略&#xff09; 一、安装git&#xff0c;安装程序…

vue启动时的错误

解决办法一&#xff1a;在vue.config.js中直接添加一行代码 lintOnSave:false 关闭该项目重新运行就可启动 解决办法二&#xff1a; 修改组件名称

步步精科技诚邀您参加2024慕尼黑上海电子展

尊敬的客户&#xff1a; 我们诚挚地邀请您参加即将于2024年7月8日至7月10日在上海新国际博览中心举办的2024慕尼黑上海电子展&#xff08;electronica China&#xff09;。此次展会汇聚了国内外优秀企业&#xff0c;展示从元器件到系统集成方案的完整产品链&#xff0c;为各行…

点云处理实战 点云平面拟合

目录 一、什么是平拟合 二、拟合步骤 三、数学原理 1、平面拟合 2、PCA过程 四、代码 一、什么是平拟合 平面拟合是指在三维空间中找到一个平面,使其尽可能接近给定的点云。最小二乘法是一种常用的拟合方法,通过最小化误差平方和来找到最优的拟合平面。 二、拟合步骤…

极验行为式验证码适配HarmonyOS 鸿蒙SDK下载

现阶段&#xff0c;越来越多的开发者正在积极加入鸿蒙生态系统。随着更多开发者的参与&#xff0c;早在去年9月&#xff0c;极验就成为首批拥有鸿蒙NEXT内测版本和手机系统测试机会的验证码供应商。 为了提高各开发者及企业客户集成鸿蒙版本行为验4.0的效率&#xff0c;方便大家…

放大招了|十亿参数大模型LLMs运行功耗仅需13W,内存使用量减少90%!

矩阵乘法&#xff08;MatMul&#xff09;历来是大型语言模型&#xff08;LLMs&#xff09;总体计算成本的主导因素&#xff0c;尤其在模型向更大维度嵌入和上下文长度发展时&#xff0c;这一成本呈指数级增长。 近期有一篇刚刚发表的论文中提出的方法完全去除了矩阵乘法操作&am…

SS8870T-3.6A 扫地机和滚刷电机的大电流电机驱动

扫地机器人已经成为现代家庭清洁的必备工具&#xff0c;而其中的关键部件——电机&#xff0c;对于其性能和用户体验起着至关重要的作用。为了确保扫地机器人的高效清洁和稳定运行&#xff0c;至少需要使用7个直流电机&#xff0c;包括行走轮、滚轮、边刷和吸尘等功能的驱动。 …

2024/5/9【贪心5/5】--代码随想录算法训练营day36|56. 合并区间、738.单调递增的数字、968.监控二叉树 (可跳过)

56. 合并区间 力扣链接 class Solution:def merge(self, intervals):result []if len(intervals) 0:return result # 区间集合为空直接返回intervals.sort(keylambda x: x[0]) # 按照区间的左边界进行排序result.append(intervals[0]) # 第一个区间可以直接放入结果集中…

专业软件测试公司分享:安全测评对于软件产品的重要性

在互联网普及的今天&#xff0c;随着各类软件的大规模使用&#xff0c;安全问题也变得愈发突出。因此&#xff0c;对软件进行全面的安全测评&#xff0c;不仅可以有效保障用户的信息安全&#xff0c;还能提升软件产品的信任度和市场竞争力。 安全测评对于软件产品的重要性就如…

SSL证书部署的安装环境

一、SSL证书常见的几种服务器环境 SSL证书可以安装部署在多种服务器环境中&#xff0c;以实现网站的HTTPS安全加密通信。正常常见的几种服务器主要分为Apache服务器、Nginx服务器、IIS服务器、Tomcat服务器。 1、Apache服务器&#xff1a; Apache是广泛使用的Web服务器软件。…

【C++】STL-stack_queue

目录 1、stack和queue的使用 1.1 最小栈 1.2 栈的弹出和压入序列 1.3 二叉树的层序遍历 2、stack和queue的模拟实现 2.1 适配器 2.2 deque 2.2.1 deque的成员变量 2.2.2 deque的迭代器 2.2.3 deque尾插元素 2.2.4 deque头插元素 2.2.5 下标访问 2.2.6 deque的不足 …

Vite: Esbuild的使用与其插件开发

概述 作为 Vite 的双引擎之一&#xff0c;Esbuild 在很多关键的构建阶段(如 依赖预编译 、 TS 语法转译 、 代码压缩 ) 让 Vite 获得了相当优异的性能&#xff0c;是 Vite 高性能的得力助手无论是在 Vite 的配置项还是源码实现中&#xff0c;都包含了不少 Esbuild 本身的基本概…

postGreSQL关系数据库介绍

什么是postGreSQL关系数据库&#xff1f; PostgreSQL 是一个强大的、开源的对象关系型数据库管理系统&#xff08;ORDBMS&#xff09;。它基于POSTQUEL查询语言的继承&#xff0c;提供了对SQL标准的广泛支持&#xff0c;并扩展了许多高级功能&#xff0c;如事务处理、多版本并…

被年轻人整不会的1688,终于开始反击了!

“我可以买贵的&#xff0c;但我不能买贵了。”成为年轻人新晋购物哲学。 最近&#xff0c;在豆瓣、小红书等社交媒体上出现了一种独特的消费趋势。在这些平台被种草之后&#xff0c;越来越多对价格敏感、注重性价比的年轻人开始挖宝“大牌平替”。他们涌入阿里巴巴旗下以批发…

配置Nginx二级域名

一、环境 &#xff08;一&#xff09;配置 1.服务器 linux CentOS 2.反向代理 Nginx 3.开放端口 云服务器开放端口80和443 二、域名备案 &#xff08;一&#xff09;腾讯云 1.腾讯云域名备案流程 备注&#xff1a;一级域名备案后&#xff0c;二级域名可以不用再备案&a…

第一个Flask程序

自学python如何成为大佬(目录):https://blog.csdn.net/weixin_67859959/article/details/139049996?spm1001.2014.3001.5501 一切准备就绪&#xff0c;现在我们开始编写第一个Flask程序&#xff0c;由于是第一个Flask程序&#xff0c;当然要从最简单的“Hello World&#xff…

Qt Object:智能即时聊天室项目

目录 1.项目介绍 2.设计思路 3.Pro文件配置 4.项目演示 5.项目开源 项目介绍 智能即时聊天室系统&#xff08;AIChatProject&#xff09;是一个高效、灵活的即时通讯解决方案。它融合了百度的开源大型语言模型——文心一言&#xff0c;通过API接口实现深度集成。系统专为聊天和…