顺序表--数据结构第一关

news2024/12/22 20:41:57

顺序表

数据结构概念

定义:数据结构是计算机存储、组织数据的⽅式

根据学过C语言的基础上,数组是最简单的数据结构

顺序表的底层就是数组

为什么呢?

例子如下:

int arr[100]={1,2,3,4,5};
//修改某一个数据:arr[pos]=x;
//插入一个元素:找到数组已有元素,再进行插入数据
//删除一个元素,找到数组已有元素,再进行删除数据    

这个情况还是我们可见的情况下,如果说是好多数组要进行这样的操作,或者很大的未知大小的数组要进行如下的操作,是不是特别麻烦

顺序表说:我虽然底层是数组,但是我提供了很多现成的方法,开箱即用,我就变成了一个很厉害的数据结构。

数组和顺序表的对比

数组(苍蝇馆子)顺序表(米其林)
炒土豆丝豪华金丝(炒土豆丝+摆盘)
蔬菜汤西湖牛肉羹(蔬菜+水+摆盘)

由此可以形象地表现出顺序表:在数组的基础上增加了增删改查的方法

顺序表也是一种线性表

线性表是具有相同性质的数据结构的集合

初步理解

蔬菜分为绿叶类、⽠类、菌菇类。

水果有:香蕉,苹果,菠萝。。。。

那线性表是具有相同性质的数据结构的集合具体表现在哪两个方面呢?

(1):物理结构:不一定连续

​ (2):逻辑结构:连续的

如图所示:

在这里插入图片描述

这个是物理结构上的理解

逻辑结构就是我们通常所认为的理解。

打个比方,我们去商店购物:如果是比较火的店就需要排队

在这里插入图片描述

右边那串像葡萄一样的,可以抽象理解为一个连续的结构,再来看数组,数组是连续存放的,我们可以通过指针的方式,去访问数组里面的元素,所以数组是逻辑结构上连续的

再来看顺序表

顺序表的底层是数组,所以它的物理结构和逻辑结构都是连续的

接下来做一个知识的铺垫引入:

int arr[10]={0};//定长数组
int* arr;//动态内存开辟,确定大小之后再去动态申请

顺序表的分类

静态顺序表

struct SeqList
{
    int arr[100];//定长数组
    int size;//顺序表当前有效的数据个数;
}

动态顺序表

struct SeqList
{
    int* arr;
    int size;//有效的数据个数
    int capcity;//空间大小
    
}

那么这两种哪一种更好呢?

首先我们来谈静态顺序表

(1)数组大小给小了,空间不够用 :如果说开发一个APP,你只提供了能储存一万个用户信息的空间,但是这款APP,却意外的火了,现在有很多很多用户想要去注册,但是没有空间可以注册,这样子给公司造成了不小的损失。

(2)数组大小给大了,空间造成了浪费:这样子也会给公司造成了一定的损失

接着我们再来谈动态顺序表:

动态增容:譬如说只开辟了100个空间,但是我们可以动态地扩容,相较于静态顺序表来说浪费的更少了

这里我们不难得出答案:动态顺序表更好
在这里插入图片描述

在这里插入图片描述

顺序表的实现

在这里插入图片描述

这就好比一本书的目录一样,头文件就相当于是目录的作用

Seq就是 sequence 的意思,也就是顺序的意思,List顾名思义就是列表

注意这里还需要创建一个源文件作为测试用叫test.c

注意来看:

#define _CRT_SECURE_NO_WARNINGS 1
//一般不推荐写静态顺序表
//以下是动态顺序表
typedef int SLDataType;
struct SeqList
{
	SLDataType* arr;
	int size;//有效的数据大小
	int capacity;//空间大小
};

为什么我这里还要重新定义int ,而不是直接写int 呢?

打个比方,我们以后进了公司,有100000000行的代码涉及到了int ,这时候领导来了一句,把其中的6000行换成char,虽然我们知道编译器有一键置换的功能,但是这个功能可不能轻易使用,我们只要换其中的6000行不是所有的,所以我们要用重命名的方法来做,提高了我们的效率。

初始化和销毁

注意点:

在这里插入图片描述

来看一些代码的实现:

头文件内的:

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
//一般不推荐写静态顺序表
//以下是动态顺序表
typedef int SLDataType;
struct SeqList
{
	SLDataType* arr;
	int size;//有效的数据大小
	int capacity;//空间大小
}SL;
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//头部插⼊删除 / 尾部插⼊删除
void SLPushBack(SL* ps, SLDataType x);
void SLPopBack(SL* ps);
void SLPushFront(SL* ps, SLDataType x);
void SLPopFront(SL* ps);

SeqList.c:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
void SLInit(SL *ps)
{
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}
void SLDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}

test.c:

#include "SeqList.h"
int main()
void SLTest01()
{
	SL sl;
	SLInit(&sl);
}
int main()
{
	SLTest01();
	return 0;
}

尾插

对尾插的概念图解:

在这里插入图片描述

ps指向的是一个数组,X=5是我要插入的数,size是我有效的数字个数,在这幅图中有4个,capacity是指空间大小

接下来是代码的实现过程了:

这是在SeqLsit.c的内容:

//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	//ps->arr[ps->size]=x;
	//++ps->size;
	ps->arr[ps->size++];//这行代码是将上面的两行代码变成了一行代码,
	//对其size进行了后置++,提高程序运行效率
}

这是在test.c的内容:

void SLTest01()
{
	SL sl;
	SLInit(&sl);
	//增删查改操作
	//测试尾插
	SLPushBack(&sl, 1);
	SLDestory(&sl);
}

但是这样做在运行的时候会出现一些问题:
当你去监视程序的时候会发现:

size和capacity为0,也就意味着没有创建顺序表去可以去接受内容

这样就给我们提了一个醒:

插入数据前先看空间够不够

代码如下:

if(ps->capacity==ps->size)

如果不够,接下来我们就要去申请空间了

申请空间就不难想到之前学过的三个有关动态开辟空间的函数:malloc,calloc,realloc

经典的三选一:我们选择realloc,因为在这三个函数中只有realloc有增容的概念,其他两个都只是开辟空间,在这里又要注意malloc和calloc的区别,calloc开辟空间的时候会对其进行初始化

接下来出现了我们的第一个问题

要申请多大的空间/一次增容多少?

在这里插入图片描述

如上图,我到底是开辟一个还是开辟n个空间呢。

直接给出结论:

增容通常是成倍数的增加,一般是2倍或3倍,但通常来说是2倍的去增容

实际上是数学推理出来的,用2或者3倍更合理

若要频繁地增容,程序运行效率大大降低

空间大小和数据个数的关系
在这里插入图片描述

从图上可以清楚地看出:空间大小和数据个数成正比的关系

以下是一些补充(感兴趣自己看,不感兴趣也无妨,不会影响学习的效率)

在数据结构中,特别是当涉及到数组这样的连续存储结构时,增容(或称为扩容)通常以倍数的形式增加,这样做的主要原因有以下几点:

  1. 减少数据移动次数:当数组需要扩容时,通常的做法是开辟一块新的、更大的内存空间,然后将原数组中的元素复制到新的内存空间中。如果每次扩容只增加少量空间,那么随着数组元素的增加,这种复制操作会频繁发生,导致时间复杂度较高。而如果以倍数形式增加容量,比如每次扩容为原来的两倍,那么虽然单次扩容时复制的元素数量较多,但复制操作的频率会大大降低,从而减少总的复制次数和时间消耗。
  2. 均摊时间复杂度为O(1):当以倍数形式扩容时,可以计算出均摊到每个元素上的复制次数是常数级别的。具体来说,假设每次扩容为原来的两倍,那么最终数组中的n个元素中,n个元素至少被复制了1次,n/2个元素至少被复制了2次,n/4个元素至少被复制了3次,以此类推。将这些复制次数相加,可以得到一个等比数列的和,其和是O(n)的。但由于这个复制次数是分摊到n个元素上的,所以均摊到每个元素上的复制次数是O(1)的。这意味着,从长期来看,每次插入或删除元素的时间复杂度是常数级别的。
  3. 空间利用率:虽然以倍数形式扩容可能会导致一定的空间浪费(因为当数组未满时就已经进行了扩容),但这种浪费是可控的,并且可以通过选择合适的扩容倍数来平衡空间利用率和性能。通常,选择2倍作为扩容倍数是一个较好的折衷方案,因为它既能保证较好的性能,又能保持相对较高的空间利用率。

综上所述,数据结构中增容以倍数的形式增加主要是为了减少数据移动次数、降低均摊时间复杂度和保持相对较高的空间利用率。

代码如下:

ps->arr = realloc(ps->arr, ps->capacity * 2*sizeof(SLDataType));

接下来我们来看我们已经写的代码:

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
void SLInit(SL *ps)
{
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}
void SLDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	//插入前先看空间够不够
	if (ps->capacity == ps->size)
	{
		//申请空间
		ps->arr = realloc(ps->arr, ps->capacity * 2*sizeof(SLDataType));
	}
	//ps->arr[ps->size]=x;
	//++ps->size;
	ps->arr[ps->size++];//这行代码是将上面的两行代码变成了一行代码,
	//对其size进行了后置++,提高程序运行效率
}

有没有发现什么问题呢?

	ps->size = ps->capcacity = 0;

我把空间初始化为0了,我怎么插入数据呢?

看代码如下:

//判断空间大小是否为0
// 三目表达式
int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;

但是不要忘了动态申请内存可能会失败,realloc申请空间失败会怎样呢?

里面会变成NULL.

例子如下:
在这里插入图片描述

还是来看这幅图:

如果这幅图我要插入的数据大于它所能存储的空间范围呢,那样子不就全都没了,竹篮打水一场空

来看代码的实现:

	SLDataType*tmp = realloc(ps->arr, ps->newCapacity * 2*sizeof(SLDataType));
	if (tmp == NULL)
	{
		perror("realloc fail!");
		exit(1);
	}
	//空间申请成功
	ps->arr = tmp;
	ps->capacity = newCapacity;

我先去判断是否为空,这里还要注意我用了*tmp去接收内容。tmp是临时变量,以防数据丢失

再来看一个坑:

在test.c文件中:

#include "SeqList.h"
int main()
void SLTest01()
{
	SL sl;
	SLInit(&sl);
	//增删查改操作
	//测试尾插
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	SLPushBack(NULL, 5);//注意看这个代码
	SLDestory(&sl);
}
int main()
{
	SLTest01();
	return 0;
}

如果我贸然地将前面的参数变为NULL,此时我们的代码还不具有健壮性,程序会出现访问冲突的问题,此时该怎么做呢?

if (ps == NULL)
{
	return;
}

在插入空间前看是否为空指针。

Tip:在程序运行的时候退出码为0,证明是正常退出的,如果不为0,那就是没有正常退出

这是一种比较温柔的解决方法

下面是比较粗暴的解决方式:

#include <assert.h>
assert(ps);//等价于assert(ps!=NULL);

头插

概念图:

在这里插入图片描述

把元素插到arr[0]的位置

大体思路如下:
在这里插入图片描述

目标是打算把最后一位有效数字往后挪一位

代码如下:

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//先让顺序表已有的数据往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] =ps-> arr[i - 1];//arr[1]=arr[0],最后一次情况是这样,由此来推断i的限制条件
	}
	ps->arr = x;
}

特别需要注意这里i的限制条件,我们不确定的时候可以先往下写,由写出的代码推出for循环的限制条件

接下来的一步我们要去打印顺序表:

void SLPrint(SL s)
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ",s.arr[i]);
	}
	printf("\n");
}

为什么这里不要取地址呢?

因为我们要取的是它的值。

但是我们去打印的时候会出现一些不太符合我们预期的结果,在头插上,这是因为有效个数没有增加:

ps->size++;

综合来看代码如下:

void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//先让顺序表已有的数据往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] =ps-> arr[i - 1];//arr[1]=arr[0],最后一次情况是这样,由此来推断i的限制条件
		ps->size++;//特别要注意了
	}
	ps->arr = x;
}

尾删

概念图

情况一:

在这里插入图片描述

情况二:

在这里插入图片描述

我们需要知道一个道理:只要写的表达式能够很好地满足增删改查数据就是好的表达式

头删

在这里插入图片描述

代码如下:

void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < size - 2; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1];
	}
	ps->size--;
}

完整的实现过程:

SeqList.h

#pragma once
#define _CRT_SECURE_NO_WARNINGS 1
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
//一般不推荐写静态顺序表
//以下是动态顺序表
typedef int SLDataType;
struct SeqList
{
	SLDataType* arr;
	int size;//有效的数据大小
	int capacity;//空间大小
}SL;
//顺序表的初始化
void SLInit(SL* ps);
//顺序表的销毁
void SLDestory(SL* ps);
//顺序表的打印
void SLPrint(SL s);
//头部插入删除 / 尾部插入删除
//插入
void SLPushBack(SL* ps, SLDataType x);
void SLPushFront(SL* ps, SLDataType x);
//删除
void SLPopBack(SL* ps);
void SLPopFront(SL* ps);

SeqList.c

#define _CRT_SECURE_NO_WARNINGS 1
#include "SeqList.h"
//专门封装一个函数用来检查空间是否够不够
void SLCheckCapacity(SL*ps)
{
	//插入前先看空间够不够
	if (ps->capacity == ps->size)
	{
		//温柔的解决方法
		if (ps == NULL)
		{
			return;
		}
		//判断空间大小是否为0
		// 三目表达式
		int newCapacity = ps->capacity == 0 ? 4 : 2 * ps->capacity;
		//申请空间
		SLDataType* tmp = realloc(ps->arr, ps->newCapacity * 2 * sizeof(SLDataType));
		if (tmp == NULL)
		{
			perror("realloc fail!");
			exit(1);
		}
		//空间申请成功
		ps->arr = tmp;
		ps->capacity = newCapacity;
	}
}
void SLInit(SL *ps)
{
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}
void SLDestory(SL* ps)
{
	if (ps->arr)
	{
		free(ps->arr);
	}
	ps->arr = NULL;
	ps->size = ps->capcacity = 0;
}
//尾插
void SLPushBack(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//ps->arr[ps->size]=x;
	//++ps->size;
	ps->arr[ps->size++]=x;//这行代码是将上面的两行代码变成了一行代码,
	//对其size进行了后置++,提高程序运行效率
}
void SLPushFront(SL* ps, SLDataType x)
{
	assert(ps);
	SLCheckCapacity(ps);
	//先让顺序表已有的数据往后挪动一位
	for (int i = ps->size; i > 0; i--)
	{
		ps->arr[i] =ps-> arr[i - 1];//arr[1]=arr[0],最后一次情况是这样,由此来推断i的限制条件
		ps->size++;//特别要注意了
	}
	ps->arr = x;
}

void SLPrint(SL s)
{
	for (int i = 0; i < s.size; i++)
	{
		printf("%d ",s.arr[i]);
	}
	printf("\n");
}
void SLPopBack(SL* ps)
{
	assert(ps);
	assert(ps->size);
	//顺序表不为空
	--ps->size;
}
void SLPopFront(SL* ps)
{
	assert(ps);
	assert(ps->size);
	for (int i = 0; i < size - 2; i++)
	{
		ps->arr[i] = ps->arr[i + 1];//arr[size-2]=arr[size-1];
	}
	ps->size--;
}

test.c

#include "SeqList.h"
int main()
void SLTest01()
{
	SL sl;
	SLInit(&sl);
	//增删查改操作
	//测试尾插
	SLPushBack(&sl, 1);
	SLPushBack(&sl, 2);
	SLPushBack(&sl, 3);
	SLPushBack(&sl, 4);
	//SLPushBack(NULL, 5);
	SLPrint(sl);
	SLPushFront(&sl, 6);
	SLPrint(sl);
	SLDestory(&sl);
}
int main()
{
	SLTest01();
	return 0;
}

思维导图

在这里插入图片描述
送大家一句话:如果你遇到困难的时候,证明你在走上坡路。
希望大家喜欢的博客,如有不足请大家指正!

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

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

相关文章

vcruntime140_1.dll是什么东东?vcruntime140_1.dll缺失的8个解决方法

当电脑出现找不到vcruntime140_1.dll,或vcruntime140_1.dll丢失无法打开软件怎么办&#xff1f;小编今天在本文详细为大家介绍解决方法与介绍vcruntime140_1.dll究竟是什么等vcruntime140_1.dll的问题。 一、vcruntime140_1.dll文件是什么 文件概述定义与功能 vcruntime140_…

校园圈子小程序系统搭建需求和需要哪些功能?APP小程序H5前后端源码交付

功能&#xff1a;小程序授权登陆&#xff0c;支持app双端&#xff0c;小程序&#xff0c;h5&#xff0c;pc端&#xff0c;手机号登陆&#xff0c;发帖&#xff0c;建圈子、发活动。可置顶推荐帖子&#xff0c;关注、粉 丝、点赞等。可作为圈子贴吧、小红书、校园社区、表白墙、…

【02】从0到1构建AI生成思维导图应用 -- 编写主页

【02】从0到1构建AI生成思维导图应用 – 编写主页 大家好&#xff01;最近自己做了一个完全免费的AI生成思维导图的网站&#xff0c;支持下载&#xff0c;编辑和对接微信公众号&#xff0c;可以在这里体验&#xff1a;https://lt2mind.zeabur.app/ 上一章&#xff1a;https:/…

【AI大模型RAG】深入探索检索增强生成(RAG)技术

目录 1. 引言2. RAG技术概述2.1 RAG技术的定义2.2 RAG技术的工作原理2.3 RAG技术的优势2.4 RAG技术的应用场景 3. RAG的工作流程3.1 输入处理3.2 索引建立3.3 信息检索3.4 文档生成3.5 融合与优化 4. RAG范式的演变4.1 初级 RAG 模型4.2 高级 RAG 模型4.3 模块化 RAG 模型优化技…

生命在于学习——Python人工智能原理(2.5.1)

五、Python的类与继承 5.1 Python面向对象编程 在现实世界中存在各种不同形态的事物&#xff0c;这些事物之间存在各种各样的联系。在程序中使用对象来映射现实中的事物&#xff0c;使用对象之间的关系描述事物之间的联系&#xff0c;这种思想用在编程中就是面向对象编程。 …

nodejs国内源下载

nodejs的官网下载太慢了 可以尝试网盘下载快一点 夸克网盘分享夸克网盘是夸克推出的一款云服务产品&#xff0c;功能包括云存储、高清看剧、文件在线解压、PDF一键转换等。通过夸克网盘可随时随地管理和使用照片、文档、手机资料&#xff0c;目前支持Android、iOS、PC、iPad。…

2024年公司加密软件排行榜(企业加密软件推荐)

在信息时代&#xff0c;企业数据安全至关重要&#xff0c;防止数据泄露和未授权访问是首要任务之一。以下是2024年备受好评的企业加密软件排行榜&#xff1a; 固信加密软件https://www.gooxion.com/ 1.固信加密软件 固信加密软件是新一代企业级加密解决方案&#xff0c;采用先…

【网络架构】lvs集群

目录 一、集群与分布式 1.1 集群介绍 1.2 分布式系统 1.3 集群设计原则 二、LVS 2.1 lvs工作原理 2.2 lvs集群体系架构 ​编辑 2.3 lvs功能及组织架构 2.4 lvs集群类型中术语 三、LVS工作模式和命令 3.1 lvs集群的工作模式 3.1.1 lvs的nat模式 3.1.2 lvs的dr模式 …

胶质瘤的发病原因及诊断方式有哪些?

胶质瘤&#xff0c;这个听起来有些陌生的名词&#xff0c;实际上是一种起源于神经胶质细胞的常见脑肿瘤。它的发病原因复杂&#xff0c;涉及遗传、环境、年龄及感染等多种因素。 首先&#xff0c;遗传因素在胶质瘤的发病中占据一席之地。某些遗传性疾病&#xff0c;如结节性硬化…

3Dmax模型渲染时的常见问题与解决方法

3Dmax是一个广为人知的三维建模工具&#xff0c;它在建筑、电影制作和游戏开发等多个领域都有着广泛的应用。尽管如此&#xff0c;在进行3Dmax模型渲染的过程中&#xff0c;用户可能会遇到一些常见问题。本文将提供这些常见问题的解决方案&#xff0c;以帮助用户提高渲染效率和…

BIO、NIO编程深入理解与直接内存、零拷贝

网路编程基本常识 一. Socket 什么是Socket Socket是对网络中不同主机上的应用进程之间进行双向通信的端点的抽象。它提供了应用层进程利用网络协议交换数据的机制&#xff0c;是应用程序与网络协议栈进行交互的接口。 说白了&#xff0c;Socket就是把TCP/IP协议族进行封装…

JOSEF约瑟 ESRW-322打滑开关 智能运算,工作稳定

产品特点 非接触式检测&#xff1a;ESRW-322打滑开关采用非接触式检测方式&#xff0c;不会对输送带造成磨损&#xff0c;提高了设备的使用寿命。 高精度测量&#xff1a;该开关具有高精度测量能力&#xff0c;可检测到的打滑率范围广泛&#xff08;0∽100%&#xff09;&#x…

LangCell:用于细胞注释的语言-细胞预训练模型

细胞身份包括细胞的各种语义&#xff0c;包括细胞类型、pathway信息、疾病信息等。从转录组数据中了解细胞身份&#xff0c;例如注释细胞类型&#xff0c;是一项基础任务。由于语义是由人类赋予的&#xff0c;如果没有cell-label pair提供监督信号&#xff0c;AI模型很难有效地…

文献解读-基因编辑-第十二期|《CRISPR-detector:快速、准确地检测、可视化和注释基因组编辑事件引起的全基因组范围突变》

关键词&#xff1a;基因组变异检测&#xff1b;全基因组测序&#xff1b;基因编辑&#xff1b; 文献简介 标题&#xff08;英文&#xff09;&#xff1a;CRISPR-detector: fast and accurate detection, visualization, and annotation of genome-wide mutations induced by g…

IDEA 安装与激活详细教程最新(附最新激活码)2099年亲测有效!

我们先从 IDEA 官网下载 IDEA 2024.1 版本的安装包&#xff0c;下载链接如下&#xff1a; https://www.jetbrains.com/idea/download/ 点击下载(下载Ultimate版)&#xff0c;静心等待其下载完毕即可。 激活方式&#xff1a; 正版专属激活码领取

自定义APT插件导致IDEA调试时StreamTrace(跟踪当前流链)报internal error(内部错误)

IDEA里面debug的时候&#xff0c;针对stream流提供了流追踪调试功能&#xff0c;方便大家调试stream流代码。 最近改其他人代码&#xff0c;需要用到这个&#xff0c;发现提示内部错误。 然后百度一圈发现没啥解决方案&#xff0c;就自己看IDEA的日志&#xff0c;看看是什么引…

css控制整个div下的所有元素中的文字放大缩小

css控制文字放大缩小 话不多说,直接上代码,我用了最简单粗暴的方法,找个下面所有的元素,然后遍历放大所有文字 add() {var div this.$refs[myDiv];var elements div.querySelectorAll("*");for (var i 0; i < elements.length; i) {var fontSize parseInt(win…

FineReport填报列权限控制

近期换东家啦&#xff0c;又回归使用帆软啦&#xff0c;对于填报报表列权限的控制我这边顺带记录一下 首先讲解下场景&#xff1a;填报报表需要不同角色决定对不同列是否有填写或者查看权限 以填写权限为例&#xff0c;首先考虑用到的是 帆软自带的权限编辑&#xff0c;其次考虑…

如何不改变 PostgreSQL 列类型#PG培训

开发应用程序并在其背后操作数据库集群时&#xff0c;会遇到一个意想不到的问题是实践与理论、开发环境与生产之间的差异。这种不匹配的一个完美例子就是更改列类型。 #PG考试#postgresql培训#postgresql考试#postgresql认证 关于如何在 PostgreSQL&#xff08;以及其他符合 SQ…

使用API有效率地管理Dynadot域名,为文件夹中的域名设置域名转发

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…