当前位置: 首页 > news >正文

【数据结构与算法】链表1:移除链表 设计链表链表反转(双指针法、递归法)

文章目录

    • 今日任务
    • 1.链表理论基础
        • (1)什么是链表?
        • (2)链表的类型
        • (3)链表的存储方式
        • (4)链表的定义
        • (5)链表的操作
        • (6)性能分析
    • 2.Leetcode203:移除链表元素
        • (1)题目
        • (2)思路
        • (3)代码实现
    • 3.Leetcode707:设计链表
        • (1)题目
        • (2)思路
        • (3)代码实现
    • 4.Leetcode206:反转链表
        • (1)题目
        • (2)思路
        • (3)双指针法
        • (4)递归法

今日任务

  • 链表理论基础

  • 203.移除链表元素

  • 707.设计链表

  • 206.反转链表

1.链表理论基础

(1)什么是链表?

链表是一种通过指针串联在一起的线性结构,每一个节点由两部分组成,一个是数据域一个是指针域(存放指向下一个节点的指针),最后一个节点的指针域指向null(空指针的意思)。

链表的入口节点称为链表的头节点也就是head。

(2)链表的类型

常见的链表类型有以下几种:

<1>单链表

单向链表是一种包含两部分的数据结构,即一个是数据部分(数据域),另一个是地址部分(指针域),其中包含下一个或后继节点的地址。节点中的地址部分也称为指针

image-20230217114232162

在单链表中,每一个节点除了包括自身的数值外,还包含了下一个节点的地址,在第三个节点它的地址部分包含的是NULL值,因为它不指向任何节点。此外,保存初始节点地址的指针称为头指针

由于单链表的指针域只保存了下一个节点的地址,因此在单链表中,只能向前遍历,而不能反向遍历

// 单向链表中节点的表示struct node 
{ 
int data; 
struct node *next; 
} 

<2>双链表

前面说了单链表中的指针域只能指向节点的下一个节点。而在双链表中,每一个节点有两个指针域,一个指向下一个节点,一个指向上一个节点

这就意味着,双向链表不仅支持向前查询,还可以向后查询

image-20230217114149969

// 双向链表中节点的表示struct node 
{ 
int data; 
struct node *next; 
struct node *prev; 
} 

<3>循环链表

循环链表,是指头节点和尾节点首位相连,以此形成一个循环结构。也可以这么认为,循环链表是单链表的变体。也就是说,循环链表没有起始节点和结束节点,我们可以朝任意方向进行遍历(向前或者向后)。

image-20230217114529563

// 循环链表中节点的表示struct node 
{ 
int data; 
struct node *next; 
} 

乍一看,循环链表和单链表节点的表示一样,其实他们之间唯一最本质的区别就是最后一个节点不指向单链表中的任何节点,因此单链表的链接部分包含一个NULL值;相反,循环链表的最后一个节点的链接部分保存着第一个节点的地址。

(3)链表的存储方式

前面在学习数组的时候我们知道,数组在内存中是连续分布的,但是链表则是通过指针域的指针 链接在内存中的各个节点上,也就是说链表中的节点在内存中不是连续分布的,而是零散分布在内存中的某个地址上,分配机制取决于操作系统的内存管理。

image-20230217120000271

在上图中我们可以看出,该链表的起始节点为2,终止节点为7,各个节点分布在内存中的不同地址空间上,通过指针串联在一起。

(4)链表的定义

给出链表节点的定义:

// 单链表
strcut ListNode{int val;	//节点上存储的元素ListNode *next;		//指向下一个节点的指针ListNode(int x): val(x),next(NULL){}	// 节点的构造函数
};

下面给出使用自己定义构造函数和使用默认构造函数的区别(推荐自定义构造函数):

1、通过自己定义构造函数初始化节点:

ListNode* head = new ListNode(5);

2、使用默认构造函数初始化节点:

ListNode* head = new ListNode();
head->val = 5;

从上面不难看出,如果使用默认构造函数的话,在初始化时是不可以直接给变量赋值的。

(5)链表的操作

<1>删除节点

我们以下图为例,目的时删除D节点:

image-20230217142406253

具体操作:

C节点的next指针指向的是D节点,而我们的需求是删除D节点,那么只需要将C节点的next指针指向E节点就可以了

此时的D节点从链表中删除,但是它依然存放在内存中,需要我们手动释放这段内存。

<2>添加节点

在下图中,我们需要在C节点和D节点中添加一个F节点:

image-20230217142827964

添加F节点,只需要将C节点的next指针指向F节点,同时F节点的next指针指向D节点,这样就完成了节点的添加。

(6)性能分析

这里我们将链表和数组做一个对比,详见下图:

image-20230217143205888

  • 数组在定义的时候,长度就是固定的,想要改动数组的长度,就需要重新定义一个新的数组。
  • 链表的长度可以是不固定的,并且可以实现动态增删,适合场景:数据量不固定、增删频繁、查询需求较少

2.Leetcode203:移除链表元素

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/remove-linked-list-elements

(1)题目

给你一个链表的头节点 head 和一个整数 val ,请你删除链表中所有满足 Node.val == val 的节点,并返回 新的头节点 。

示例 1:

image-20230217143757762

输入:head = [1,2,6,3,4,5,6], val = 6
输出:[1,2,3,4,5]

示例 2:

输入:head = [], val = 1
输出:[]

示例 3:

输入:head = [7,7,7,7], val = 7
输出:[]

提示:

  • 列表中的节点数目在范围 [0, 104] 内
  • 1 <= Node.val <= 50
  • 0 <= val <= 50

(2)思路

案例1:

链表:1->4->2->4 目的:移除元素4

image-20230217144046231

其实这道题还是比较简单的,首先可以看出它是一个单链表,那么我们定义好节点的数据域和地址域,让节点1的next指针指向节点2,并且让节点2的next指针指向NULL,那么这道题就算完成了,最后的结果也就是下面这张图。

image-20230217144342989

那么此外我们还需要完成节点4的内存回收工作!

案例二:

由于考虑到在实际应用中可能存在对头节点的删除需求,所以我们这里也额外做个分析。

对于链表的操作有两种形式:

  • 1.直接使用原来的链表进行删除操作。
  • 2.设置一个虚拟头节点再进行删除操作。

<操作1>:直接使用原来的链表进行移除

移除头节点和移除其他节点的擦欧总是不一样的,因为链表的其他节点都是通过前面一个节点来移除房前节点,而头节点没有前节点。

那么对于头节点的移除,需要将头节点向后移动一位就可以了,同时记得将原头节点从内存中释放。

image-20230217145654957

对于操作一这种方法虽然可以实现,但是无疑是增加了代码的逻辑性,需要我们单独写一段逻辑处理头节点。那么这样的话不妨我们试试操作2的方法。

<操作2>:设置一个虚拟头节点再进行删除操作

如何设置虚拟头节点,首先我们需要给链表添加一个虚拟头节点作为新的头节点,同时我们移除旧的头节点,也就是下图中的元素1,并且将新的头节点的next指针指向第二个节点4

image-20230217150125673

具体实现我们详见代码。

(3)代码实现

// 操作1实现:直接使用原来的链表进行删除操作class Solution {
public:ListNode* removeElements(ListNode* head, int val) {// 删除头结点while (head != NULL && head->val == val) { // head != NULL:这里判断头节点不为空是因为后续需要对头节点的值进行操作,如果为空就相当于操作空指针,编译会报错。ListNode* tmp = head;head = head->next;delete tmp;		// 此处需要对旧的头节点进行内存回收}// 删除非头结点ListNode* cur = head;	// 当前节点while (cur != NULL && cur->next!= NULL) {// cur->next!= NULL:这里是同样的道理,不可操作空指针if (cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}return head;}
};

这里需要注意几点:

  • 对于可能存在节点的值为空的情况我们要避免空指针操作,否则编译会报错
  • 操作1的关键代码就是下面的这两部分

image-20230217153228463

// 操作2实现:设置一个虚拟头节点再进行删除操作class Solution {
public:ListNode* removeElements(ListNode* head, int val) {ListNode* dummyHead = new ListNode(0); // 设置一个虚拟头结点dummyHead->next = head; // 将虚拟头结点指向head,这样方面后面做删除操作ListNode* cur = dummyHead;while (cur->next != NULL) {if(cur->next->val == val) {ListNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;} else {cur = cur->next;}}head = dummyHead->next;delete dummyHead;return head;}
};

3.Leetcode707:设计链表

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/design-linked-list

(1)题目

设计链表的实现。您可以选择使用单链表或双链表。单链表中的节点应该具有两个属性:val 和 next。val 是当前节点的值,next 是指向下一个节点的指针/引用。如果要使用双向链表,则还需要一个属性 prev 以指示链表中的上一个节点。假设链表中的所有节点都是 0-index 的。

在链表类中实现这些功能:

  • get(index):获取链表中第 index 个节点的值。如果索引无效,则返回-1。
  • addAtHead(val):在链表的第一个元素之前添加一个值为 val 的节点。插入后,新节点将成为链表的第一个节点。
  • addAtTail(val):将值为 val 的节点追加到链表的最后一个元素。
  • addAtIndex(index,val):在链表中的第 index 个节点之前添加值为 val 的节点。如果 index 等于链表的长度,则该节点将附加到链表的末尾。如果 index 大于链表长度,则不会插入节点。如果index小于0,则在头部插入节点。
  • deleteAtIndex(index):如果索引 index 有效,则删除链表中的第 index 个节点。

示例:

MyLinkedList linkedList = new MyLinkedList();
linkedList.addAtHead(1);
linkedList.addAtTail(3);
linkedList.addAtIndex(1,2);   //链表变为1-> 2-> 3
linkedList.get(1);            //返回2
linkedList.deleteAtIndex(1);  //现在链表是1-> 3
linkedList.get(1);            //返回3

提示:

  • 0 <= index, val <= 1000
  • 请不要使用内置的 LinkedList 库。
  • get, addAtHead, addAtTail, addAtIndex 和 deleteAtIndex 的操作次数不超过 2000。

(2)思路

分析题目给出的要求,主要是需要完成以下功能:

  • 获取链表第index个节点的值
  • 在链表的最前面插入一个节点
  • 在链表的最后面插入一个节点
  • 在链表第index个节点面前插入一个节点
  • 删除链表的第index个节点

(3)代码实现

class MyLinkedList {
public:// 定义链表节点结构体struct LinkedNode {int val;LinkedNode* next;LinkedNode(int val):val(val), next(nullptr){}};// 初始化链表MyLinkedList() {_dummyHead = new LinkedNode(0); // 这里定义的头结点 是一个虚拟头结点,而不是真正的链表头结点_size = 0;}// 获取到第index个节点数值,如果index是非法数值直接返回-1, 注意index是从0开始的,第0个节点就是头结点int get(int index) {if (index > (_size - 1) || index < 0) {return -1;}LinkedNode* cur = _dummyHead->next;while(index--){ // 如果--index 就会陷入死循环cur = cur->next;}return cur->val;}// 在链表最前面插入一个节点,插入完成后,新插入的节点为链表的新的头结点// 这里选择插入新的头节点采用的是操作1,详情可查看第二小节中的思路void addAtHead(int val) {LinkedNode* newNode = new LinkedNode(val);newNode->next = _dummyHead->next;_dummyHead->next = newNode;_size++;}// 在链表最后面添加一个节点void addAtTail(int val) {LinkedNode* newNode = new LinkedNode(val);LinkedNode* cur = _dummyHead;while(cur->next != nullptr){cur = cur->next;}cur->next = newNode;_size++;}// 在第index个节点之前插入一个新节点,例如index为0,那么新插入的节点为链表的新头节点。// 如果index 等于链表的长度,则说明是新插入的节点为链表的尾结点// 如果index大于链表的长度,则返回空// 如果index小于0,则在头部插入节点void addAtIndex(int index, int val) {if(index > _size) return;if(index < 0) index = 0;        LinkedNode* newNode = new LinkedNode(val);LinkedNode* cur = _dummyHead;while(index--) {cur = cur->next;}newNode->next = cur->next;cur->next = newNode;_size++;}// 删除第index个节点,如果index 大于等于链表的长度,直接return,注意index是从0开始的void deleteAtIndex(int index) {if (index >= _size || index < 0) {return;}LinkedNode* cur = _dummyHead;while(index--) {cur = cur ->next;}LinkedNode* tmp = cur->next;cur->next = cur->next->next;delete tmp;_size--;}// 打印链表void printLinkedList() {LinkedNode* cur = _dummyHead;while (cur->next != nullptr) {cout << cur->next->val << " ";cur = cur->next;}cout << endl;}
private:int _size;LinkedNode* _dummyHead;};

4.Leetcode206:反转链表

来源:力扣(LeetCode)
链接:https://leetcode.cn/problems/reverse-linked-list

(1)题目

给你单链表的头节点 head ,请你反转链表,并返回反转后的链表。

示例 1:

image-20230217163726826

输入:head = [1,2,3,4,5]
输出:[5,4,3,2,1]

示例 2:

image-20230217163749967

输入:head = [1,2]
输出:[2,1]

示例 3:

输入:head = []
输出:[]

提示:

  • 链表中节点的数目范围是 [0, 5000]
  • -5000 <= Node.val <= 5000

进阶:链表可以选用迭代或递归方式完成反转。你能否用两种方法解决这道题?

(2)思路

链表的反转,只需要改变next指针的指向即可。

(3)双指针法

对于链表的反转问题,我们可以通过使用双指针的方式来解决这个问题。

  • cur指针,指向链表的头节点
  • pre指针,定义为cur指针的前一个节点,也就是让cur指针原本指向后一位的指针指向pre指针的地址
class Solution {
public:ListNode* reverseList(ListNode* head) {ListNode* temp; // 作为一个临时节点,保存cur的下一个节点ListNode* cur = head;ListNode* pre = NULL;	// 之所以初始化为空,就是为了让cur节点指向pre节点,而我们的目标就是尾节点反转成目标的头节点,也就是NULL// 所以此处当pre节点和cur节点遍历到尾节点时,也就是cur指向NULL,这也就意味反转完成,因此while()的值设为curwhile(cur) {temp = cur->next;  // 保存一下 cur的下一个节点,因为接下来要改变cur->nextcur->next = pre; // 翻转操作// 更新pre 和 cur指针pre = cur;cur = temp;}return pre;	// 返回的是新链表的头节点pre}
};

(4)递归法

前面讲了双指针法,其实递归法与之逻辑都是大体一样的,不过对于递归,我们有自前向后递归、以及自后向前递归两种方法。

// 递归法:自前向后class Solution {
public:ListNode* reverse(ListNode* pre,ListNode* cur){if(cur == NULL) return pre;ListNode* temp = cur->next;cur->next = pre;// 可以和双指针法的代码进行对比,如下递归的写法,其实就是做了这两步// pre = cur;// cur = temp;return reverse(cur,temp);}ListNode* reverseList(ListNode* head) {// 和双指针法初始化是一样的逻辑// ListNode* cur = head;// ListNode* pre = NULL;return reverse(NULL, head);}};
// 递归法:自后向前class Solution {
public:ListNode* reverseList(ListNode* head) {// 边缘条件判断if(head == NULL) return NULL;if (head->next == NULL) return head;// 递归调用,翻转第二个节点开始往后的链表ListNode *last = reverseList(head->next);// 翻转头节点与第二个节点的指向head->next->next = head;// 此时的 head 节点为尾节点,next 需要指向 NULLhead->next = NULL;return last;}
}; 

相关文章:

【数据结构与算法】链表1:移除链表 设计链表链表反转(双指针法、递归法)

文章目录今日任务1.链表理论基础&#xff08;1&#xff09;什么是链表&#xff1f;&#xff08;2&#xff09;链表的类型&#xff08;3&#xff09;链表的存储方式&#xff08;4&#xff09;链表的定义&#xff08;5&#xff09;链表的操作&#xff08;6&#xff09;性能分析2.…...

山东大学软件学院面向对象简答题整理【个人向】

面向对象简答题整理【个人向】 0.试用面向对象语言简述改写和重定义的异同&#xff0c;以及方法绑定时的差别 改写是子类的方法和父类的方法具有相同的方法名和类型签名重定义是子类的方法和父类的方法方法名相同但类型签名不同在方法绑定时&#xff0c;改写是动态绑定&#…...

JAVA时间类及JAVA8新时间类

文章目录Java旧时间类关系图![在这里插入图片描述](https://img-blog.csdnimg.cn/e2c2c26c841e40bdb9cc85d0fc4bc1df.png)GMT、时间戳、统一标准时间、时区Java时间类创建时间类示例java.text.DateFormat时间格式转换java.util.Calendar总结Java时间类Java8新时间类InstantCloc…...

ASEMI代理FGH60N60SFD,安森美FGH60N60SFD原装IGBT

编辑-Z 安森美FGH60N60SFD原装IGBT参数&#xff1a; 型号&#xff1a;FGH60N60SFD 集电极到发射极电压&#xff08;VCES&#xff09;&#xff1a;600V 栅极到发射极电压&#xff08;VGES&#xff09;&#xff1a;20V 收集器电流&#xff08;IC&#xff09;&#xff1a;120…...

【云原生之Docker实战】使用dokcer部署web端vscode

【云原生之Docker实战】使用dokcer部署web端vscode 一、vscode-server介绍二、检查本地docke环境1.检查系统版本2.检查docker版本3.检查docker状态三、下载vscode镜像四、部署vscode-server1.创建安装目录2.创建vscode容器3.查看vscode容器状态4.查看vscode容器日志五、访问vsc…...

Docker安装Tomcat、mysql、redis

目录 前言 一、安装Tomcat 二、安装mysql &#xff08;一&#xff09;简单版 &#xff08;二&#xff09;实战版 三、安装redis 前言 镜像可以先去Docker Hub Container Image Library | App Containerization 左上角搜&#xff0c;然后点进入可以看到具体的命令&#…...

【python 基础篇 八】python的常用数据类型操作-------集合

目录1.集合的基本概念2.集合的定义2.1 可变集合 set定义2.2 不可变集合 fronzenset 定义2.3 集合定义的注意事项3.单一集合的常用操作4. 集合之间操作4.1 交集4.2 并集4.3 差集4.4 判定1.集合的基本概念 无序的&#xff0c;不可随机访问的&#xff0c;不可重复的元素集合与数学…...

Spring框架中问题补充

BeanFactory 和 ApplicationContext BeanFactory和ApplicationContext是接口。BeanFactory接口时spring框架的顶层接口&#xff0c;定义管理bean的最基本的方法&#xff0c;例如获取实例、判断等功能。 DefaultListableBeanFactory实现BeanFactory 接口,是主要的创建bean的工…...

【Leedcode】顺序表必备的三道面试题(附图解)

顺序表必备的三道面试题&#xff08;附图解&#xff09; 文章目录顺序表必备的三道面试题&#xff08;附图解&#xff09;前言一、第一题1.题目2.思路图解3.源码二、第二题1.题目2.思路图解3.源码三、第三题1.题目2.思路图解3.源码总结前言 本文给大家介绍三道顺序表学习过程中…...

SOFA Weekly|开源人、本周贡献 issue 精选

SOFA WEEKLY | 每周精选 筛选每周精华问答&#xff0c;同步开源进展欢迎留言互动&#xff5e;SOFAStack&#xff08;Scalable Open Financial Architecture Stack&#xff09;是蚂蚁集团自主研发的金融级云原生架构&#xff0c;包含了构建金融级云原生架构所需的各个组件&#…...

2023美赛 ICM E题详细版思路

问题E&#xff1a;光污染注&#xff1a;楷体为题目原文&#xff0c;宋体为思路部分首先&#xff0c;我们需要考虑的就是美赛ABEF的核心问题&#xff0c;数据。这里E题是以光污染为背景的题目&#xff0c;首当其冲的我们就需要收集一些数据以支撑我们的模型。对于E题提出的问题&…...

【LeetCode】剑指 Offer(3)

目录 写在前面&#xff1a; 题目&#xff1a;剑指 Offer 09. 用两个栈实现队列 - 力扣&#xff08;Leetcode&#xff09; 题目的接口&#xff1a; 解题思路&#xff1a; 代码&#xff1a; 过啦&#xff01;&#xff01;&#xff01; 写在最后&#xff1a; 写在前面&…...

springboot simple (13) springboot Elasticsearch(Elasticsearch8.5.1)

这里首先简单的介绍了Elasticsearch&#xff0c;然后实现了springboot集成Elasticsearch。 版本&#xff1a; Elasticsearch&#xff1a;v8.5.1 Kibana&#xff1a;v8.5.1 springboot集成elasticsearch有两种方式。 1&#xff09;rest客户端RestHingLevelClient&#xff1b; …...

《爆肝整理》保姆级系列教程python接口自动化(十七)--Json 数据处理---一次爬坑记(详解)

简介 有些 post 的请求参数是 json 格式的&#xff0c;这个前面发送post 请求里面提到过&#xff0c;需要导入 json模块处理。现在企业公司一般常见的接口因为json数据容易处理&#xff0c;所以绝大多数返回数据也是 json 格式的&#xff0c;我们在做判断时候&#xff0c;往往只…...

分享111个HTML旅游交通模板,总有一款适合您

分享111个HTML旅游交通模板&#xff0c;总有一款适合您 111个HTML旅游交通模板下载链接&#xff1a;https://pan.baidu.com/s/1VHJSBVJbj4PQpPAwxysJBg?pwd8b17 提取码&#xff1a;8b17 Python采集代码下载链接&#xff1a;采集代码.zip - 蓝奏云 汽车租赁平台网页模板 汽…...

guava中ImmutableList使用示例详解

ImmutableList是一个不可变、线程安全的列表集合&#xff0c;它只会获取传入对象的一个副本&#xff0c;而不会影响到原来的变量或者对象&#xff0c;如下代码&#xff1a; int a 23;ImmutableList<Integer> list ImmutableList.of(a, 12);System.out.println(list);a …...

ASE28N50-ASEMI高压N沟道MOS管ASE28N50

编辑-Z ASE28N50在TO-247封装里的静态漏极源导通电阻&#xff08;RDS(ON)&#xff09;为200mΩ&#xff0c;是一款N沟道高压MOS管。ASE28N50的最大脉冲正向电流ISM为110A&#xff0c;零栅极电压漏极电流(IDSS)为1uA&#xff0c;其工作时耐温度范围为-55~150摄氏度。ASE28N50功…...

MyBatis缓存

文章目录MyBatis的缓存1、缓存概述2、MyBatis的一级缓存2.1 一级缓存的使用2.2 一级缓存的失效3、MyBatis的二级缓存3.1 二级缓存的开启3.2 二级缓存的失效3.2 二级缓存相关配置4、系统缓存的查询顺序5、EHCache的使用5.1 EHCache基本介绍5.2 EHCache的基本使用5.3 EHCache配置…...

Linux环境下(CentOS 7)安装Java(JDK8)

Linux环境下(CentOS 7)安装Java(JDK8) 一、安装教程 1.1 首先&#xff0c;进入oracle官网下载jdk8的安装包&#xff0c;下载地址如下&#xff0c;这里以 jdk-8u121-linux-x64.tar.gz安装包为例。 http://www.oracle.com/technetwork/java/javase/downloads/jdk8-downloads-21…...

基于STM32L431+Liteos的串口空闲中断加DMA循环接收

①MCU为STM32L431&#xff0c;使用串口2。 ②Liteos采用接管中断的方式。 STM32CubeMX配置生成串口代码&#xff1a; 串口DMA接收和发送配置区别是接收采用循环模式&#xff0c;发送为正常模式。 将生成的代码移植到liteos工程中&#xff0c;由于使用的接管中断的方式&#…...

Python爬虫实战:研究MechanicalSoup库相关技术

一、MechanicalSoup 库概述 1.1 库简介 MechanicalSoup 是一个 Python 库,专为自动化交互网站而设计。它结合了 requests 的 HTTP 请求能力和 BeautifulSoup 的 HTML 解析能力,提供了直观的 API,让我们可以像人类用户一样浏览网页、填写表单和提交请求。 1.2 主要功能特点…...

深入浅出Asp.Net Core MVC应用开发系列-AspNetCore中的日志记录

ASP.NET Core 是一个跨平台的开源框架&#xff0c;用于在 Windows、macOS 或 Linux 上生成基于云的新式 Web 应用。 ASP.NET Core 中的日志记录 .NET 通过 ILogger API 支持高性能结构化日志记录&#xff0c;以帮助监视应用程序行为和诊断问题。 可以通过配置不同的记录提供程…...

【Linux】shell脚本忽略错误继续执行

在 shell 脚本中&#xff0c;可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行&#xff0c;可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令&#xff0c;并忽略错误 rm somefile…...

Cesium1.95中高性能加载1500个点

一、基本方式&#xff1a; 图标使用.png比.svg性能要好 <template><div id"cesiumContainer"></div><div class"toolbar"><button id"resetButton">重新生成点</button><span id"countDisplay&qu…...

HTML 列表、表格、表单

1 列表标签 作用&#xff1a;布局内容排列整齐的区域 列表分类&#xff1a;无序列表、有序列表、定义列表。 例如&#xff1a; 1.1 无序列表 标签&#xff1a;ul 嵌套 li&#xff0c;ul是无序列表&#xff0c;li是列表条目。 注意事项&#xff1a; ul 标签里面只能包裹 li…...

macOS多出来了:Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用

文章目录 问题现象问题原因解决办法 问题现象 macOS启动台&#xff08;Launchpad&#xff09;多出来了&#xff1a;Google云端硬盘、YouTube、表格、幻灯片、Gmail、Google文档等应用。 问题原因 很明显&#xff0c;都是Google家的办公全家桶。这些应用并不是通过独立安装的…...

postgresql|数据库|只读用户的创建和删除(备忘)

CREATE USER read_only WITH PASSWORD 密码 -- 连接到xxx数据库 \c xxx -- 授予对xxx数据库的只读权限 GRANT CONNECT ON DATABASE xxx TO read_only; GRANT USAGE ON SCHEMA public TO read_only; GRANT SELECT ON ALL TABLES IN SCHEMA public TO read_only; GRANT EXECUTE O…...

从零实现STL哈希容器:unordered_map/unordered_set封装详解

本篇文章是对C学习的STL哈希容器自主实现部分的学习分享 希望也能为你带来些帮助~ 那咱们废话不多说&#xff0c;直接开始吧&#xff01; 一、源码结构分析 1. SGISTL30实现剖析 // hash_set核心结构 template <class Value, class HashFcn, ...> class hash_set {ty…...

浅谈不同二分算法的查找情况

二分算法原理比较简单&#xff0c;但是实际的算法模板却有很多&#xff0c;这一切都源于二分查找问题中的复杂情况和二分算法的边界处理&#xff0c;以下是博主对一些二分算法查找的情况分析。 需要说明的是&#xff0c;以下二分算法都是基于有序序列为升序有序的情况&#xf…...

uniapp 字符包含的相关方法

在uniapp中&#xff0c;如果你想检查一个字符串是否包含另一个子字符串&#xff0c;你可以使用JavaScript中的includes()方法或者indexOf()方法。这两种方法都可以达到目的&#xff0c;但它们在处理方式和返回值上有所不同。 使用includes()方法 includes()方法用于判断一个字…...