速通数据结构第二站 顺序表

文章目录

速通数据结构与算法系列

1 速通数据结构与算法第一站 复杂度        http://t.csdnimg.cn/sxEGF

感谢佬们支持!


目录

系列文章目录

  • 前言
  • 一、顺序表
  •       0 结构体
  •       1 接口声明
  •       2 初始化和销毁
  •       3 扩容函数
  •       4 打印和判空
  •       5 尾插
  •       6 尾删
  •       7 头插
  •       8 头删
  •       9 查找
  •      10insert (指定位置下一个插入)
  •      11erase  (删除指定位置)
  •      12完整代码
  • 二、顺序表OJ
  •       1 移除元素
  •       2 删除有序数组中的重复项
  •       3 合并两个有序数组
  • 总结

前言

           我们要接触到的第一种数据结构类型是线性表,线性表的定义是n个具有相同特性的数据元素的有限序列。常见的有:顺序表,链表,栈,队列,字符串……

线性表的逻辑结构是线性的,即一条连续的直线,但是其物理结构不一定是连续的,在物理上一般为数组和链式。

在这里我们要先区分一个概念:逻辑结构和物理结构

逻辑结构是一个抽象的结构,是我们研究某种东西时为了便于理解的一种归纳的思想

而物理结构则是真实的存储结构

举个例子来看,磁盘是什么结构?我们拿到一个磁盘会发现它是扇形的,他存储单元是一个个扇区,倘若我们把这些扇形一个个拉直,最后得到一条线,所以它的逻辑结构就是线性表

--》


一、顺序表

顺序表是用一段物理连续存储单元依次存储数据元素的线性结构,一般采用数组存储,利用数组来完成增删查改操作。

我们来浅浅实现一波,先创3个文件:test.c  sqlist.c   sqlist.h

在sqlist.h下……

为了达到C语言版的所谓泛型,模板,我们设一个宏

typedef int SLDataType;

我们先来写它的结构体

结构体


typedef struct sqlist
{
	SLDataType* a;
	//数据个数
	int size;
	//容量
	int capacity;
}SL;

注意:在STL的实现中,vector的结构体成员(成员变量)有3个,int* start,int* end,int* endofstorage三个指针(迭代器,此处先暂且认为是int*类型),对应关系为

start=_a;
finish=_a+_size;
endofstorage=_a+capacity;

这样设计的好处就是,当我们swap(vector1,vector2)时;成本将非常低,因为只需交换3个指针而已。


为了方便我们之后STL的学习,我们接口的命名风格都按STL的来

我们在seqlist.h中包一下需要用到的头文件,

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>

接口声明

并声明如下接口

//打印函数
void SeqListPrint(SL* ps);

//扩容函数
void BuyListNode(SL* ps);

//初始化
void SeqListInit(SL* ps);

//销毁
void SeqListDestroy(SL* ps);

//判空
bool SeqListCheckCapacity(SL* ps);

//尾插
void SeqListPushBack(SL* ps, SLDataType x);

//尾删
void SeqListPopBack(SL* ps);

//头插
void SeqListPushFront(SL* ps, SLDataType x);

//头删
void SeqListPopFront(SL* ps);

//查找 找到了返回下标,没找到返回-1 
int SeqListFind(SL* ps, SLDataType x);

//指定pos位置后插
void SeqListInsert(SL* ps, SLDataType x, int pos);

//指定pos位置删
void SeqListErase(SL* ps, int pos);

初始化和销毁

考虑到动态内存泄漏的问题,我们先来实现初始化及其销毁函数

要做的事很简单,初始化时指针置空,size和capacity给个0即可

(其中要注意判空ps,因为我们不知道不知道传入的ps是否为空)

//初始化
void SeqListInit(SL* ps)
{
    assert(ps);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

//销毁
void SeqListDestroy(SL* ps)
{
    assert(ps);
	free(ps->a);
    ps->a=NULL;
	ps->capacity = ps->size = 0;

}

扩容函数

为了便于调用,我们封装出一个扩容函数来

由于刚开始容量为0,我们第一次给4,之后进行二倍扩容

(二倍扩容采用的是SGI STL的扩容策略)

//扩容函数
void BuyListNode(SL* ps)
{
    assert(ps);
	//0就给4,不是就给capacity2倍
	int newcapacity = (ps->capacity == 0) ? 4 : (ps->capacity * 2);
	SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
	//扩容失败
	if (NULL == tmp)
	{
		printf("realloc fail");
		exit(-1);
	}
	//扩容成功
	ps->a = tmp;
	ps->capacity = newcapacity;
}

我们简单地来测试一下

SL sl;
	SeqListInit(&sl);

	SeqListDestroy(&sl);

(确实挺不错的)


打印和判空

下来我们再写个简单的打印和判空

打印就简单了,遍历打印;判空的逻辑就是size是否等于0

//打印函数
void SeqListPrint(SL* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
}
//判空
bool SeqListCheckCapacity(SL* ps)
{
    assert(ps);
	return ps->size == 0;
}

 接下来就该是顺序表核心的插入删除操作了

尾插

我们先来进行尾插,尾插简单,在数组的最后插就行了,顺便更新一下size

注意:在插之前,我们先要考虑是否需要扩容的问题

void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//插
	ps->a[ps->size] = x;
	ps->size++;
}

另外 我们知道,此时的扩容并非在数组后面直接扩容,而是再开一块空间,并将原来的数据拷过来,并释放原空间,在STL的学习中会有所谓迭代器失效的问题,因为之前的空间没了

所以指向之前空间的迭代器就会失效,我们不能用了,但是在C语言中,这种场景则不太容易碰到。


尾删

尾删就更简单了,我们直接--size即可,但是我们需要断言一下size>0

//尾删
void SeqListPopBack(SL* ps)
{
	assert(ps);

	//断言一下size,size要大于0
	assert(ps->size > 0);
	ps->size--;

}

显然,我们发现,尾插,尾删的时间复杂度都是O(1)的。


我们来测试一下尾插和尾删

SL sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl,1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);

	SeqListPrint(&sl);
	printf("\n");

	SeqListPopBack(&sl);
	SeqListPushBack(&sl, 5);

	SeqListPrint(&sl);

 

(没问题)


下来就是有点麻烦的头插和头删了

头插

头插的逻辑是这样的,我们需要讲数组往后挪一格,再在第一个位置做插入

-》

其中这个挪就有意思了,是从前往后挪还是从后往前挪呢?

当然是从后往前挪,不然会覆盖数据

//头插
void SeqListPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//插
	//从后往前挪数据
	int len = ps->size-1;
	while (len>=0)
	{
		ps->a[len+1] = ps->a[len];
		--len;
	}
	ps->a[0] = x;
	ps->size++;

}

头删

头删也需要挪动数据,不过和头插恰好相反,他需要从前往后开始挪

//头删
void SeqListPopFront(SL* ps)
{
	assert(ps);
	//挪数据
	int len = 0;
	while (len <= ps->size - 1)
	{
		ps->a[len] = ps->a[len + 1];
		++len;
	}
	ps->size--;
}

显然,头插和头删的时间复杂度都是O(n),所以精明的STL并没有单独提供头插头删操作

我们再来简单的测试一下

SL s2;
	SeqListInit(&s2);
	SeqListPushFront(&s2, 1);
	SeqListPushFront(&s2, 2);
	SeqListPushFront(&s2, 3);
	SeqListPushFront(&s2, 4);

	SeqListPrint(&s2);
	printf("\n");
	SeqListPopFront(&s2);

(同样没有任何问题)


查找

下来我们写一下查找

查找的逻辑很简单,遍历数组,找到了返回下标,没找到返回-1

//查找 找到了返回下标,没找到返回-1 
int SeqListFind(SL* ps, SLDataType x)
{
	for (int i = 0; i < ps->size ; ++i)
	{
		if (x == ps->a[i])
		{
			return i;
		}
	}
    return -1;
}

 查找是为之后的两个函数服务的:insert 和erase

因为在实际运用时,我们一般都是先找到某个元素,再插入/删除

我们写的是删除指定位置和在指定位置的下一个插入

(STL提供的是删除指定位置和指定位置前一个插入)

 写过了之前的头删,写这个insert就简单了

insert

我们依然需要从后往前插的方式,而且在之前需要判断一下pos的合法性

//指定pos位置后插
void SeqListInsert(SL* ps, SLDataType x, int pos)
{
	assert(pos>=0&&pos <= ps->size);
	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//挪动数据
	int len = ps->size;
	while (len-pos+1)
	{
		ps->a[len + 1] = ps->a[len];
		--len;
	}
	ps->a[pos + 1] = x;
	++ps->size;
}

erase同理

erase

//指定pos位置删
void SeqListErase(SL* ps,  int pos)
{
	assert(pos>=0&&pos <= ps->size);
	//pos+1往前挪
	int len = ps->size-1;
	while (len-pos)
	{
		ps->a[len-1] = ps->a[len];
		len--;
	}
	--ps->size;
}

我们再来简单的测试一下

SL s3;
	SeqListInit(&s3);
	SeqListPushBack(&s3, 1);
	SeqListPushBack(&s3, 2);
	SeqListPushBack(&s3, 3);
	SeqListPushBack(&s3, 4);
	SeqListPushBack(&s3, 5);


	SeqListPrint(&s3);
	printf("\n");

	int pos=SeqListFind(&s3,4);
	printf("%d\n", pos);
	//SeqListInsert(&s3, 7, pos);

	SeqListPrint(&s3);
	printf("\n");
    SeqListInsert(&s3, 8, pos);
	SeqListInsert(&s3, 9, pos);
	SeqListErase(&s3, pos);

	SeqListPrint(&s3);

 


12 完整代码

 sqlist.h

#pragma once
#include<stdio.h>
#include<stdlib.h>
#include<stdbool.h>
#include<assert.h>


typedef int SLDataType;

typedef struct sqlist
{
	SLDataType* a;
	//数据个数
	int size;
	//容量
	int capacity;
}SL;


//打印函数
void SeqListPrint(SL* ps);

//扩容函数
void BuyListNode(SL* ps);

//初始化
void SeqListInit(SL* ps);

//销毁
void SeqListDestroy(SL* ps);

//判空
bool SeqListCheckCapacity(SL* ps);

//尾插
void SeqListPushBack(SL* ps, SLDataType x);

//尾删
void SeqListPopBack(SL* ps);

//头插
void SeqListPushFront(SL* ps, SLDataType x);

//头删
void SeqListPopFront(SL* ps);

//查找 找到了返回下标,没找到返回-1 
int SeqListFind(SL* ps, SLDataType x);

//指定pos位置后插
void SeqListInsert(SL* ps, SLDataType x, int pos);

//指定pos位置删
void SeqListErase(SL* ps, int pos);

sqlist.c

#include "seqlist.h"


//初始化
void SeqListInit(SL* ps)
{
	assert(ps);
	ps->a = NULL;
	ps->capacity = ps->size = 0;
}

//销毁
void SeqListDestroy(SL* ps)
{
	assert(ps);
	free(ps->a);
	ps->a = NULL;
	ps->capacity = ps->size = 0;

}


//扩容函数
void BuyListNode(SL* ps)
{
	assert(ps);
	//0就给4,不是就给capacity2倍
	int newcapacity = (ps->capacity == 0) ? 4 : (ps->capacity * 2);
	SLDataType* tmp = (SLDataType*)realloc(ps->a, newcapacity * sizeof(SLDataType));
	//扩容失败
	if (NULL == tmp)
	{
		printf("realloc fail");
		exit(-1);
	}
	//扩容成功
	ps->a = tmp;
	ps->capacity = newcapacity;
}

//打印函数
void SeqListPrint(SL* ps)
{
	assert(ps);
	for (int i = 0; i < ps->size; ++i)
	{
		printf("%d ", ps->a[i]);
	}
}

void SeqListPushBack(SL* ps, SLDataType x)
{
	assert(ps);

	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//插
	ps->a[ps->size] = x;
	ps->size++;
}

//尾删
void SeqListPopBack(SL* ps)
{
	assert(ps);

	//断言一下size,size要大于0
	assert(ps->size > 0);
	ps->size--;

}

//头插
void SeqListPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//插
	//从后往前挪数据
	int len = ps->size - 1;
	while (len >= 0)
	{
		ps->a[len + 1] = ps->a[len];
		--len;
	}
	ps->a[0] = x;
	ps->size++;

}

//头删
void SeqListPopFront(SL* ps)
{
	assert(ps);
	//挪数据
	int len = 0;
	while (len <= ps->size - 1)
	{
		ps->a[len] = ps->a[len + 1];
		++len;
	}
	ps->size--;

}

//查找 找到了返回下标,没找到返回-1 
int SeqListFind(SL* ps, SLDataType x)
{
	for (int i = 0; i < ps->size; ++i)
	{
		if (x == ps->a[i])
		{
			return i;
		}
	}
	return -1;

}

//指定pos位置后插
void SeqListInsert(SL* ps, SLDataType x, int pos)
{
	assert(pos >= 0 && pos <= ps->size);
	//考虑扩容
	if (ps->capacity == ps->size)
	{
		BuyListNode(ps);
	}
	//挪动数据
	int len = ps->size;
	printf("%d\n", len);
	while (len - pos + 1)
	{
		ps->a[len + 1] = ps->a[len];
		--len;
	}
	ps->a[pos + 1] = x;
	++ps->size;
}

//指定pos位置删
void SeqListErase(SL* ps, int pos)
{
	assert(pos >= 0 && pos <= ps->size);
	//pos+1往前挪
	int len = ps->size - 1;
	while (len - pos)
	{
		ps->a[len - 1] = ps->a[len];
		len--;
	}
	--ps->size;
}

test.c(测试代码)

#include "seqlist.h"

void test1()
{
	SL sl;
	SeqListInit(&sl);
	SeqListPushBack(&sl,1);
	SeqListPushBack(&sl, 2);
	SeqListPushBack(&sl, 3);
	SeqListPushBack(&sl, 4);

	SeqListPrint(&sl);
	printf("\n");

	SeqListPopBack(&sl);
	SeqListPushBack(&sl, 5);

	SeqListPrint(&sl);

	SeqListDestroy(&sl);

}

void test2()
{
	SL s2;
	SeqListInit(&s2);
	SeqListPushFront(&s2, 1);
	SeqListPushFront(&s2, 2);
	SeqListPushFront(&s2, 3);
	SeqListPushFront(&s2, 4);

	SeqListPrint(&s2);
	printf("\n");
	SeqListPopFront(&s2);
	SeqListPrint(&s2);

	SeqListDestroy(&s2);

}

void test3()
{
	SL s3;
	SeqListInit(&s3);
	SeqListPushBack(&s3, 1);
	SeqListPushBack(&s3, 2);
	SeqListPushBack(&s3, 3);
	SeqListPushBack(&s3, 4);
	SeqListPushBack(&s3, 5);


	SeqListPrint(&s3);
	printf("\n");

	int pos=SeqListFind(&s3,4);
	SeqListInsert(&s3, 7, pos);

	SeqListPrint(&s3);
	printf("\n");

	SeqListInsert(&s3, 8, pos);
	SeqListInsert(&s3, 9, pos);
	SeqListErase(&s3, pos);

	SeqListPrint(&s3);


}

int main()
{
	test3();
	return 0;
}

二、顺序表OJ

学完了顺序表的实现,我们可以写一些有关顺序表的OJ题


1 移除元素

题目链接: . - 力扣(LeetCode)

这个题就是简单的双指针,我们可以定义两个变量, src用来遍历数组,dst用来存放不是val的值,并标记移除元素后的新长度

由于它要的是新长度,所以我们不用真的删除那些元素。

int removeElement(int* nums, int numsSize, int val)
{
    int src = 0;
    int dst = 0;

    while (src < numsSize)
    {
        if (nums[src] != val)
        {
            nums[dst] = nums[src];
            ++dst;
            ++src;
        }
        else
        {
            ++src;
        }
    }
    return dst;
}

关于双指针这类算法,后续我们会进行系统的学习和刷题哦~


2 删除有序数组中的重复项

题目链接:  . - 力扣(LeetCode)

由于要求原地删除,所以我们不能再搞一个数组,把不重复的元素push_back进去

这道题我们依旧采用双指针来做

但是我们需要三个指针,两个cur,next用来遍历,一个dst用来记录不重复元素的个数

我们的逻辑是这样,如果cur和next指向值相同的数就让next++,指向值不相同的数时

用dst下标记录cur指向的值,再让dst++,让cur去next的位置,再让next++

如图所示

-》

-》

(此时第一个下标就记录了0这个元素)

但是还有个问题:到了要结束的时候,此时cur,next指向的元素不同,next++就跳出了循环

所以最后一个元素我们在循环结束后要再补充至dst下标上

由此可得代码如下

int removeDuplicates(int* nums, int numsSize)
{
	int cur = 0;
	int next = 1;
	int dst = 0;
	//考虑为空
	if (numsSize == 0)
	{
		return 0;
	}
	while (next < numsSize)
	{
		if (nums[next] == nums[prev])
		{
			next++;
		}
		else
		{
			nums[dst++] = nums[prev];
			prev = next;
			next++;
		}
	}
    nums[dst++]=nums[prev];

	return dst;
}

3 合并两个有序数组

题目链接 : . - 力扣(LeetCode)

显然,我们的任务是把nums2的拷入nums1中,

两个数组一个给一个指针int i=0,int j=0,遍历数组找小的;再标记一个dst指针,将较小者插入nums[dst++];

当两个数组有一个走完了另一个数组的元素再依次拷入剩下的位置即可。

啊但是!

当你画了图模拟一遍之后就会发现,如果我们从前往后开始会有覆盖的可能

如图,当nums2的2和nums1的3比较时,由于2<3,显然2要到3的位置,所以这个3就会被覆盖

那怎么办呢?

以我们刚才头插头删的经验来看,从前往后会覆盖,那我们就从后往前

所以我的指针变为int end1=m-1,int end2=n-1,int end=m+n-1。比较的时候也是比较大的

所以代码如下

void merge(int* nums1, int nums1Size, int m, int* nums2, int nums2Size, int n)
{

	int end1=m-1;
    int end2=n-1;
    int end=m+n-1;
	while (end1>=0 && end2>=0)
	{
		if (nums1[end1] > nums2[end2])
		{
			nums1[end--] = nums1[end1--];
		}
		else
		{
			nums1[end--] = nums2[end2--];
		}
	}
		//有一个走完了
			while (end2>=0)
			{
				nums1[end--] = nums2[end2--];
			}
}

总结

 做总结,这篇博客我们学习了了顺序表,顺序表的优势是由于有下标,可以随机访问尾插尾删效率高。下篇博客我们要学习可能有些些许难得链表,如果你的指针有些遗忘了,建议去复习一下指针哦~

水平有限,还请各位大佬指正。如果觉得对你有帮助的话,还请三连关注一波。希望大家都能拿到心仪的offer哦。

每日gitee侠:今天你交gitee了嘛

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

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

相关文章

B2902A是德科技B2902A精密型电源

181/2461/8938产品概述&#xff1a; Agilent B2902A 精密源/测量单元 (SMU) 是一款 2 通道、紧凑且经济高效的台式 SMU&#xff0c;能够源和测量电压和电流。它用途广泛&#xff0c;可以轻松、高精度地执行 I/V&#xff08;电流与电压&#xff09;测量。4 象限源和测量功能的集…

RabbitMQ安装及使用笔记

RabbitMQ安装及使用笔记 RabbitMQ是一个开源的消息代理软件&#xff0c;它实现了高级消息队列协议&#xff08;AMQP&#xff09;&#xff0c;用于在分布式系统中进行消息传递。 1.安装 利用docker load命令加载mq镜像 docker load -i mq.tar 基于Docker来安装RabbitMQ&#xff…

【QT入门】 QListWidget各种常见用法详解之列表模式

往期回顾 【QT入门】 Qt代码创建布局之setLayout使用-CSDN博客 【QT入门】 Qt代码创建布局之多重布局变换与布局删除技巧-CSDN博客 【QT入门】 QTabWidget各种常见用法详解-CSDN博客 【QT入门】 QListWidget各种常见用法详解之列表模式 QListWidget有列表和图标两种显示模式&a…

Blenderproc渲染6D位姿估计数据集

https://github.com/DLR-RM/BlenderProc/tree/main/examples/datasets/bop_challenge 目录 1.3d渲染原理 2.步骤 3.代码 生成mask_all 4.难例渲染 物体高反光​编辑​编辑强弱灯光(明暗)​编辑​编辑​编辑物体xyz范围缩小 物体重复 干扰物&#xff08;自定义干扰物遮…

C#实现身份证格式验证(自建异常实现提醒)

基本信息 中国居民身份证的格式包括18位数字&#xff0c;这些数字分别代表不同的信息&#xff1a; 第1、2位数字表示省份代码。 第3、4位数字表示城市代码。 第5、6位数字表示区县代码。 第7至14位数字表示出生年、月、日&#xff08;其中7、8、9、10位是年&#xff0c;11、12…

整合SpringSecurity+JWT实现登录认证

一、关于 SpringSecurity 在 Spring Boot 出现之前&#xff0c;SpringSecurity 的使用场景是被另外一个安全管理框架 Shiro 牢牢霸占的&#xff0c;因为相对于 SpringSecurity 来说&#xff0c;SSM 中整合 Shiro 更加轻量级。Spring Boot 出现后&#xff0c;使这一情况情况大有…

python实战之PyQt5桌面软件

一. 演示效果 二. 准备工作 1. 使用pip 下载所需包 pyqt5 2. 下载可视化UI工具 QT Designer 链接&#xff1a;https://pan.baidu.com/s/1ic4S3ocEF90Y4L1GqYHPPA?pwdywct 提取码&#xff1a;ywct 3. 可视化UI工具汉化 把上面的链接打开, 里面有安装和汉化包, 前面的路径还要看…

基于SSM学生信息管理系统

采用技术 基于SSM学生信息管理系统的设计与实现~ 开发语言&#xff1a;Java 数据库&#xff1a;MySQL 技术&#xff1a;SpringMVCMyBatis 工具&#xff1a;IDEA/Ecilpse、Navicat、Maven 页面展示效果 总体功能设计 登录页面 后台首页 学生信息页面 添加学生用户 编辑…

Java代码混淆技术最佳实践与案例分享

摘要 本文探讨了代码混淆在保护Java代码安全性和知识产权方面的重要意义。通过混淆技术&#xff0c;可以有效防止代码被反编译、逆向工程或恶意篡改&#xff0c;提高代码的安全性。常见的Java代码混淆工具如IPAGuard、Allatori、DashO、Zelix KlassMaster和yGuard等&#xff0…

单链表算法库

singlelist.cpp #include "singlelist.h"/************************************************** ①函数名: CreatList_Head 功 能: 头插法建立单链表 参 数: (1)LinkList *&L: 传入的单链表指针地址(2)ElemType Array_used[]:要用来建表的数组(3)int Array_nu…

win 11环境配置 之 python(cmd 输入 python --version 输出为空)

当我安装好python后&#xff0c;在 cmd 终端输入 python 和 python --version 均无任何输出时&#xff0c;就知道有问题。 在 vscode 下载好 python插件后&#xff0c;编写demo文件&#xff0c;可以执行成功。 因此得出原因是 win 环境变量配置有问题 具体错误问题&#xff1a;…

BabySQL【2019极客大挑战】

知识点&#xff1a; 功能分析 登录界面一般是 where username and password 可以从username出手&#xff0c;注释掉and语句单引号闭合绕过 通过测试和报错信息发现是一个单引号读取输入可以单引号闭合绕过关键字过滤 or and 过滤 || &&替换双写绕过select from wher…

飞凌嵌入式即将亮相德国纽伦堡「Embedded World 2024」

2024年德国纽伦堡嵌入式展览会&#xff08;Embedded World 2024&#xff09;将于4月9日~4月11日盛大开幕&#xff0c;本届展会将展示最新的电子技术与应用&#xff0c;涵盖了半导体、嵌入式系统、电源、电池、测试仪器、智能制造、电子设计自动化等众多领域&#xff0c;并将汇集…

Aigtek:电压放大器对参数的要求是什么

电压放大器是一种用于增大输入信号幅度的电子设备&#xff0c;它在各种应用中发挥着重要的作用。为了确保电压放大器的性能和可靠性&#xff0c;对其参数有一定的要求。下面安泰电子将介绍电压放大器的几个关键参数&#xff0c;包括增益、带宽、输入/输出阻抗和噪声等&#xff…

Win10 搭建FTP存储服务器站点【超详细教程】

目录 第一步&#xff1a;打开控制面板>程序 第二步&#xff1a;win10左下角搜索IIS并打开 第三步&#xff1a;右键网站&#xff0c;选择添加FTP站点 第四步&#xff1a;添加FTP站点名称 第五步&#xff1a;添加IP地址和端口 第六步&#xff1a;身份验证与授权信息 第…

系统架构图怎么画

画架构图是架构师的一门必修功课。 对于架构图是什么这个问题&#xff0c;我们可以按以下等式进行概括&#xff1a; 架构图 架构的表达 架构在不同抽象角度和不同抽象层次的表达&#xff0c;这是一个自然而然的过程。 不是先有图再有业务流程、系统设计和领域模型等&#…

LLM2LLM: Boosting LLMs with Novel Iterative Data Enhancement

LLM2LLM: Boosting LLMs with Novel Iterative Data Enhancement 相关链接&#xff1a;arXiv GitHub 关键字&#xff1a;LLM、Data Augmentation、Fine-tuning、NLP、Low-data Regime 摘要 预训练的大型语言模型&#xff08;LLMs&#xff09;目前是解决绝大多数自然语言处理任…

助力低碳出行 | 基于ACM32 MCU的电动滑板车方案

前言 随着智能科技的快速发展&#xff0c;电动滑板车的驱动系统也得到了长足的发展。国内外的电动滑板车用电机驱动系统分为传统刷式电机和无刷电机两种类型。其中&#xff0c;传统的刷式电机已经逐渐被无刷电机所取代&#xff0c;无刷电机的性能和寿命都更出色&#xff0c;已成…

Uibot6.0 (RPA财务机器人师资培训第5天 ) 报销汇总机器人案例实战

训练网站&#xff1a;泓江科技 (lessonplan.cn)https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https://laiye.lessonplan.cn/list/ec0f5080-e1de-11ee-a1d8-3f479df4d981https…

SAP BTP云上一个JVM与DB Connection纠缠的案例

前言 最近在CF (Cloud Foundry) 云平台上遇到一个比较经典的案例。因为牵扯到JVM &#xff08;app进程&#xff09;与数据库连接两大块&#xff0c;稍有不慎&#xff0c;很容易引起不快。 在云环境下&#xff0c;有时候相互扯皮的事蛮多。如果是DB的问题&#xff0c;就会找DB…