数据结构从入门到精通——顺序表

顺序表

  • 前言
  • 一、线性表
  • 二、顺序表
    • 2.1概念及结构
    • 2.2 接口实现
    • 2.3 数组相关面试题
    • 2.4 顺序表的问题及思考
  • 三、顺序表具体实现代码
    • 顺序表的初始化
    • 顺序表的销毁
    • 顺序表的打印
    • 顺序表的增容
    • 顺序表的头部/尾部插入
    • 顺序表的头部/尾部删除
    • 指定位置之前插入数据和删除指定位置数据
    • 顺序表元素的查找
  • 四、顺序表完整代码
    • text.h
    • text.c
    • main.c


前言

顺序表是一种常见的线性数据结构,它使用一段连续的存储单元依次存储数据元素。这种数据结构的特点是逻辑上相邻的元素在物理存储位置上也相邻,因此可以快速地访问表中的任意元素。

顺序表的实现通常依赖于数组,数组是一种静态的数据结构,一旦创建,其大小就是固定的。这意味着在顺序表中插入或删除元素可能会导致空间的浪费或不足。例如,如果在一个已经满了的顺序表中插入一个新元素,就需要重新分配更大的数组空间,并将原有元素复制到新数组中,这是一个相对耗时的操作。

然而,顺序表在访问元素时具有很高的效率。由于元素在内存中是连续存储的,计算机可以直接通过计算偏移量来访问任意位置的元素,这种访问方式的时间复杂度为O(1)。相比之下,链表等动态数据结构在访问元素时可能需要遍历多个节点,效率较低。

顺序表还支持快速的元素查找。通过索引,我们可以在常数时间内找到表中的任意元素。这种特性使得顺序表在处理需要频繁查找操作的场景时表现出色。

总的来说,顺序表是一种高效、简单的数据结构,适用于需要快速访问和查找元素的场景。然而,它的固定大小特性也限制了其在需要频繁插入和删除操作的场景中的应用。在实际应用中,我们需要根据具体的需求和场景来选择合适的数据结构。


一、线性表

线性表(linear list)是n个具有相同特性的数据元素的有限序列。 线性表是一种在实际中广泛使用的数据结构,常见的线性表:顺序表、链表、栈、队列、字符串…

线性表在逻辑上是线性结构,也就说是连续的一条直线。但是在物理结构上并不一定是连续的,线性表在物理上存储时,通常以数组和链式结构的形式存储。

在这里插入图片描述

二、顺序表

2.1概念及结构

顺序表是用一段物理地址连续的存储单元依次存储数据元素的线性结构,一般情况下采用数组存储。在数组上完成数据的增删查改。

顺序表一般可以分为:

  1. 静态顺序表:使用定长数组存储元素。
    在这里插入图片描述
  2. 动态顺序表:使用动态开辟的数组存储。
    在这里插入图片描述

2.2 接口实现

静态顺序表只适用于确定知道需要存多少数据的场景。静态顺序表的定长数组导致N定大了,空间开多了浪费,开少了不够用。所以现实中基本都是使用动态顺序表,根据需要动态的分配空间大小,所以下面我们实现动态顺序表。

typedef int SLDataType;
// 顺序表的动态存储
typedef struct SeqList
{SLDataType* array;  // 指向动态开辟的数组size_t size ;       // 有效数据个数size_t capicity ;   // 容量空间的大小
}SeqList;
// 基本增删查改接口
// 顺序表初始化
void SeqListInit(SeqList* psl);
// 检查空间,如果满了,进行增容
void CheckCapacity(SeqList* psl);
// 顺序表尾插
void SeqListPushBack(SeqList* psl, SLDataType x);
// 顺序表尾删
void SeqListPopBack(SeqList* psl);
// 顺序表头插
void SeqListPushFront(SeqList* psl, SLDataType x);
// 顺序表头删
void SeqListPopFront(SeqList* psl);
// 顺序表查找
int SeqListFind(SeqList* psl, SLDataType x); 
// 顺序表在pos位置插入x
void SeqListInsert(SeqList* psl, size_t pos, SLDataType x);
// 顺序表删除pos位置的值
void SeqListErase(SeqList* psl, size_t pos);
// 顺序表销毁
void SeqListDestory(SeqList* psl);
// 顺序表打印
void SeqListPrint(SeqList* psl);

2.3 数组相关面试题

  1. 原地移除数组中所有的元素val,要求时间复杂度为O(N),空间复杂度为O(1)
  2. 删除排序数组中的重复项
  3. 合并两个有序数组

2.4 顺序表的问题及思考

问题:

  1. 中间/头部的插入删除,时间复杂度为O(N)
  2. 增容需要申请新空间,拷贝数据,释放旧空间。会有不小的消耗。
  3. 增容一般是呈2倍的增长,势必会有一定的空间浪费。例如当前容量为100,满了以后增容到
    200,我们再继续插入了5个数据,后面没有数据插入了,那么就浪费了95个数据空间。

思考:如何解决以上问题呢?

三、顺序表具体实现代码

顺序表的初始化

void SLInit(SL* p);//顺序表的初始化
void SLInit(SL* p)
{p->arr = NULL;//动态开辟数组的地址置为空指针p->capacity = 0;//数组容量置为0p->size = 0;//数组下标置为0或-1,具体看你需要哪一种下标
}

顺序表的初始化是数据结构学习中不可或缺的一步,它指的是为一个预先分配了固定大小内存空间的线性表分配存储空间,并设置其初始状态。在顺序表中,数据元素在内存中是连续存放的,这种存储方式使得我们可以通过下标直接访问任何位置的元素,从而实现了快速的元素访问。

顺序表的初始化通常包括分配内存空间、设定初始容量、以及可能的初始化所有元素为某一默认值。初始化操作的正确与否直接关系到后续数据操作的效率与正确性。

以C语言为例,顺序表可以用数组来实现。在初始化时,我们通常会定义一个结构体来表示顺序表,这个结构体包含数组本身、数组的大小(即当前已存储的元素数量)以及数组的最大容量(即预先分配的内存空间大小)。

顺序表的销毁

void SLDestroy(SL* p);//顺序表的销毁
void SLDestroy(SL* p)
{assert(p);int i = 0; free(p->arr);SLInit(p);
}

在数据结构和算法的世界里,顺序表作为一种基本的线性表结构,承载着数据的存储和访问功能。然而,正如任何资源的生命周期一样,顺序表的使用也需要在结束时进行适当的销毁和清理,以确保内存的有效利用和系统的稳定运行。

顺序表的销毁,主要涉及到内存的释放。当一个顺序表不再需要使用时,我们必须将其所占用的内存空间归还给操作系统,避免内存泄漏。内存泄漏是程序运行过程中未能正确释放不再使用的内存空间,长时间累积下来会导致可用内存空间减少,最终可能导致程序运行缓慢甚至崩溃。

销毁顺序表的过程通常包括以下步骤:

  1. 遍历顺序表,释放其中存储的每一个数据元素。如果数据元素是指针类型,需要确保这些指针指向的内存也被正确释放。

  2. 释放顺序表本身所占用的内存空间。这通常通过调用相应的内存释放函数(如C语言中的free()函数)来实现。

  3. 将顺序表的头指针或引用设置为nullnullptr,表示该顺序表已经不再有效,防止后续代码错误地访问或操作已销毁的顺序表。

  4. 在某些情况下,可能还需要进行额外的清理工作,如关闭与顺序表相关的文件、释放其他相关资源等。

通过以上步骤,我们可以确保顺序表在不再使用时能够被正确地销毁,从而保持程序的内存安全和稳定运行。在实际编程中,我们应该始终遵循资源管理的最佳实践,确保在适当的时候释放不再需要的资源,避免内存泄漏和其他潜在问题。

顺序表的打印

void SLprint(SL p);//顺序表的打印
void SLprint(SL p)
{for (int i = 0; i < p.size; i++){printf("%5d", p.arr[i]);}printf("\n");
}

顺序表的打印通常指的是将顺序表中的所有元素按照一定的格式输出到控制台或其他输出设备上。这个过程通常涉及到遍历顺序表中的所有元素,并将它们转换为人类可读的格式。在打印顺序表时,我们通常会选择一种易于阅读和理解的方式,如按照元素在表中的顺序依次打印,或者使用特定的分隔符将不同的元素分隔开。

顺序表的增容

在这里插入图片描述

void SLCheckCapacity(SL* ps);//顺序表的增容
void SLCheckCapacity(SL* p)
{SL* a;assert(p);int Datacapaity = 0;if (p->size == p->capacity){Datacapaity = 0 ? 4 : 2 * p->capacity;//三目运算符a = (DataType*)realloc(p->arr, Datacapaity * sizeof(DataType));//使得扩容按照2倍增长assert(a);p->arr = a;}p->capacity = Datacapaity;
}

顺序表是一种线性数据结构,它使用一段连续的存储空间来存储元素。当顺序表中的元素数量达到其当前容量上限时,就需要进行增容操作,以确保可以继续添加新的元素。

增容操作的核心思想是为顺序表分配更多的连续存储空间,并将原有的元素复制到新的存储空间中。这通常涉及到两个主要步骤:分配新的存储空间和元素迁移。

分配新的存储空间是增容操作的第一步。顺序表会根据其当前容量和扩容因子来计算出新的容量。扩容因子是一个大于1的常数,用于确定每次增容时应该增加多少存储空间。例如,如果扩容因子为2,那么每次增容时新的容量将是原容量的两倍。

在分配了新的存储空间之后,接下来就是元素迁移的步骤。这一步将顺序表中原有的元素从旧的存储空间复制到新的存储空间中。为了保证数据的完整性和正确性,复制过程必须小心谨慎地进行。通常,复制过程会从顺序表的第一个元素开始,逐个复制到新的存储空间的相应位置,直到所有元素都被复制完毕。

完成元素迁移后,顺序表就可以继续使用新的存储空间来存储新的元素了。同时,顺序表的容量上限也得到了提升,可以容纳更多的元素。

需要注意的是,增容操作虽然可以扩展顺序表的容量,但也会带来一定的性能开销。因为每次增容都需要分配新的存储空间并进行元素迁移,这些操作都需要消耗一定的时间和资源。因此,在设计和实现顺序表时,需要权衡扩容的时机和频率,以避免频繁的增容操作对性能产生负面影响。

为了优化性能,可以在顺序表的使用过程中采取一些策略来减少增容的次数。例如,可以在添加元素之前先检查顺序表的容量是否足够,如果不足够则提前进行增容操作,以避免在添加元素时触发频繁的增容。此外,还可以根据实际应用场景和数据特点来选择合适的扩容因子,以平衡存储空间的利用率和增容操作的开销。

顺序表的头部/尾部插入

在这里插入图片描述

//顺序表的头部/尾部插入
void SLPushBack(SL* p, DataType x);
void SLPushFront(SL* p, DataType x);
void SLPushBack(SL* p, DataType x)//顺序表的尾插
{assert(p);SLCheckCapacity(p);//增容p->arr[p->size++] = x;
}void SLPushFront(SL* p, DataType x)//顺序表的头插
{assert(p);SLCheckCapacity(p);//增容for (int i = p->size; i > 0; i--){p->arr[i] = p->arr[i - 1];}p->arr[0] = x;p->size++;
}

顺序表的头部/尾部插入是顺序表操作中的基本功能,它们直接影响了顺序表的数据存储和访问效率。顺序表,又称数组列表,是一种线性表的数据结构,其特点是元素在内存中是连续存储的。这种存储方式使得顺序表在访问元素时具有很高的效率,因为可以通过下标直接定位到元素的位置。然而,在插入或删除元素时,顺序表的表现就不如链表等其他数据结构了。

在顺序表的头部插入元素时,需要将所有已存在的元素向后移动一位,以腾出空间给新插入的元素。这种操作的时间复杂度是O(n),其中n是顺序表的长度。因此,对于频繁在头部插入元素的场景,顺序表并不是最优的数据结构选择。

相比之下,在顺序表的尾部插入元素则相对高效。因为尾部是顺序表的一个“开放”端,新元素可以直接添加到这个位置,而不需要移动其他元素。这种操作的时间复杂度是O(1),即常数时间复杂度,意味着无论顺序表有多大,尾部插入的效率都是相同的。

在实际应用中,顺序表的头部/尾部插入操作常常用于实现各种算法和数据结构。例如,在某些需要动态维护数据集合的场景中,我们可以使用顺序表来存储数据,并根据需要在头部或尾部进行插入操作。此外,顺序表还可以用于实现栈(Stack)和队列(Queue)等数据结构,其中栈通常使用顺序表的头部进行插入和删除操作,而队列则使用头部进行删除操作,使用尾部进行插入操作。

需要注意的是,虽然顺序表在访问元素时具有很高的效率,但在插入和删除元素时可能会遇到性能瓶颈。因此,在选择数据结构时,我们需要根据具体的应用场景和需求来权衡各种因素,以选择最适合的数据结构。

顺序表的头部/尾部删除

在这里插入图片描述

在这里插入图片描述

//顺序表的头部/尾部删除
void SLPopBack(SL* p);
void SLPopFront(SL* p);
void SLPopBack(SL* p)
{assert(p);assert(p->size);p->size--;
}
void SLPopFront(SL* p)
{assert(p);assert(p->size);for (int i = 0; i < p->size - 1; i++){p->arr[i] = p->arr[i + 1];}p->size--;
}

顺序表的头部/尾部删除是数据结构中常见的操作,它们分别涉及到对顺序表的首个元素和最后一个元素的移除。这两种操作在多种应用场景中都具有重要的意义,比如缓存管理、消息队列、数据库索引等。

在顺序表(数组)中实现头部删除操作,通常需要将数组中的所有元素向前移动一位,以填补被删除元素的位置。这种操作的时间复杂度为O(n),其中n为数组的长度。如果顺序表是动态分配的,并且有足够的空间,也可以采用标记删除的方式,即简单地将头部元素标记为已删除,而不实际移动其他元素。但这种方法需要额外的逻辑来跟踪哪些元素是已删除的,因此可能会增加空间和时间上的开销。

相比之下,尾部删除操作通常更为简单和高效。在顺序表中,尾部元素总是位于数组的最后一个位置,因此删除它不需要移动其他元素。只需将数组的最后一个元素的位置标记为未使用,或者如果使用的是动态数组,可以减少其容量以释放未使用的空间。这种操作的时间复杂度通常为O(1)。

然而,需要注意的是,虽然尾部删除在单个操作上可能更快,但在频繁进行头部删除的情况下,顺序表可能不是最优的数据结构选择。在这种情况下,使用链表可能更为合适,因为链表在头部和尾部删除操作上的时间复杂度都是O(1)。

指定位置之前插入数据和删除指定位置数据

//指定位置之前插入数据
//删除指定位置数据
void SLInsert(SL* p, int pos, DataType x);
void SLErase(SL* p, int pos);
void SLInsert(SL* p, int pos, DataType x)
{assert(p);assert(pos>=0 && pos <= p->size);SLCheckCapacity(p);for (int i = p->size; i >= pos; i--){p->arr[i] = p->arr[i - 1];}p->arr[pos] = x;p->size++;
}
void SLErase(SL* p, int pos)
{assert(p);assert(pos >= 0 && pos <= p->size);for (int i = pos - 1; i < p->size; i++){p->arr[i] = p->arr[i + 1];}p->size--;
}

指定位置之前插入数据和删除指定位置数据是编程中常见的操作,尤其在处理列表、数组、字符串等数据结构时。这些操作不仅对于数据的管理和维护至关重要,而且在很多算法和程序设计中也扮演着重要角色。

在插入数据时,我们通常需要考虑以下几个因素:插入的位置、要插入的数据以及插入后数据结构的完整性。

在删除指定位置的数据时,我们需要确保删除操作不会破坏数据结构的其余部分。
需要注意的是,在进行插入和删除操作时,我们需要确保索引的有效性。如果索引超出数据结构的范围,那么程序会抛出异常。因此,在实际编程中,我们通常需要在进行这些操作之前先检查索引的有效性。

此外,插入和删除操作的时间复杂度也是我们需要考虑的因素。在大多数数据结构中,插入和删除操作的时间复杂度都是O(n),其中n是数据结构的长度。这意味着,随着数据结构的增长,这些操作所需的时间也会增加。因此,在选择数据结构时,我们需要根据实际需求来权衡各种因素,包括插入和删除操作的频率、数据结构的长度以及所需的空间等。

总的来说,指定位置之前插入数据和删除指定位置数据是编程中常见的操作,我们需要熟练掌握这些操作的方法和技巧,以便在实际编程中能够灵活应用。同时,我们还需要注意操作的有效性和时间复杂度等问题,以确保程序的正确性和效率。

顺序表元素的查找

//顺序表元素的查找
int SLFind(SL p, DataType x);
int SLFind(SL* p, DataType x)
{assert(p);for (int i = 0; i < p->size; i++){if (p->arr[i] == x)return i + 1;}return -1;
}

顺序表元素的查找是计算机科学中的一个基本问题,它涉及到在一个有序或无序的列表中查找特定的元素。在各种实际应用中,如数据库管理、搜索引擎、编程语言中的数据结构等,顺序表元素的查找都扮演着重要的角色。

对于顺序表元素的查找,最基础的算法是线性查找。线性查找的思想是从表的第一个元素开始,逐个比较每个元素,直到找到目标元素或遍历完整个表。这种查找方法的时间复杂度为O(n),其中n为表的长度。虽然线性查找简单易懂,但在处理大数据量时,其效率往往不能满足要求。

为了提高查找效率,人们设计了更为高效的查找算法,如二分查找。二分查找只适用于有序的顺序表,其基本思想是将表分为两半,通过比较目标元素与中间元素的大小,决定在哪一半继续查找,如此反复,直到找到目标元素或确定目标元素不存在于表中。二分查找的时间复杂度为O(log n),在数据量较大时,其效率远高于线性查找。

除了二分查找,还有一些其他的查找算法,如插值查找和斐波那契查找等。插值查找是对二分查找的一种改进,它根据目标元素在表中的大致位置,选择一个更接近于目标元素的中间元素进行比较,从而减少比较次数。斐波那契查找则是利用斐波那契数列的性质,通过计算斐波那契数来确定查找范围,进一步提高查找效率。

在实际应用中,选择哪种查找算法取决于具体的需求和场景。对于有序的顺序表,二分查找、插值查找和斐波那契查找等高效算法是更好的选择;而对于无序的顺序表,线性查找可能是唯一可行的选择。此外,还可以根据表的大小、元素的分布等因素来选择合适的查找算法。

四、顺序表完整代码

text.h

#pragma once
#include <stdio.h>
#include <stdlib.h>
#include <assert.h>
typedef int DataType;静态顺序表
//typedef struct Seqlist
//{
//	DataType data[10];
//	int size;
//}Seqlist;//动态顺序表
typedef struct Seqlist
{DataType* arr;int size;int capacity;
}SL;void SLCheckCapacity(SL* ps);//顺序表的增容void SLInit(SL* p);//顺序表的初始化
void SLDestroy(SL* p);//顺序表的销毁
void SLprint(SL p);//顺序表的打印//顺序表的头部/尾部插入
void SLPushBack(SL* p, DataType x);
void SLPushFront(SL* p, DataType x);//顺序表的头部/尾部删除
void SLPopBack(SL* p);
void SLPopFront(SL* p);//指定位置之前插入数据
//删除指定位置数据
void SLInsert(SL* p, int pos, DataType x);
void SLErase(SL* p, int pos);
int SLFind(SL p, DataType x);

text.c

#include"text.h"
void SLCheckCapacity(SL* p)
{SL* a;assert(p);int Datacapaity = 0;if (p->size == p->capacity){Datacapaity = 0 ? 4 : 2 * p->capacity;a = (DataType*)realloc(p->arr, Datacapaity * sizeof(DataType));assert(a);p->arr = a;}p->capacity = Datacapaity;
}void SLInit(SL* p)
{p->arr = NULL;p->capacity = 0;p->size = 0;
}
void SLDestroy(SL* p)
{int i = 0; for (i = 0; i < p->size; i++){free(p->arr[i]);}SLInit(p);
}
void SLprint(SL p)
{for (int i = 0; i < p.size; i++){printf("%5d", p.arr[i]);}printf("\n");
}void SLPushBack(SL* p, DataType x)
{assert(p);SLCheckCapacity(p);p->arr[p->size++] = x;
}void SLPushFront(SL* p, DataType x)
{assert(p);SLCheckCapacity(p);for (int i = p->size; i > 0; i--){p->arr[i] = p->arr[i - 1];}p->arr[0] = x;p->size++;
}void SLPopBack(SL* p)
{assert(p);assert(p->size);p->size--;
}
void SLPopFront(SL* p)
{assert(p);assert(p->size);for (int i = 0; i < p->size - 1; i++){p->arr[i] = p->arr[i + 1];}p->size--;
}void SLInsert(SL* p, int pos, DataType x)
{assert(p);assert(pos>=0 && pos <= p->size);SLCheckCapacity(p);for (int i = p->size; i >= pos; i--){p->arr[i] = p->arr[i - 1];}p->arr[pos] = x;p->size++;
}
void SLErase(SL* p, int pos)
{assert(p);assert(pos >= 0 && pos <= p->size);for (int i = pos - 1; i < p->size; i++){p->arr[i] = p->arr[i + 1];}p->size--;
}int SLFind(SL* p, DataType x)
{assert(p);for (int i = 0; i < p->size; i++){if (p->arr[i] == x)return i + 1;}return -1;
}

main.c

#include"text.h"void slTest01() {SL sl;SLInit(&sl);SLPushBack(&sl, 1);SLPushBack(&sl, 2);SLPushBack(&sl, 3);SLPushBack(&sl, 4);SLprint(sl);      //1 2 3 4SLPushBack(&sl, 5);SLprint(sl);SLPushFront(&sl, 5);SLPushFront(&sl, 6);SLPushFront(&sl, 7);SLprint(sl);       //7 6 5 1 2 3 4SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLPopBack(&sl);SLprint(sl);   //1 2SLPopFront(&sl);SLPopFront(&sl);SLPopFront(&sl);//SLPopFront(&sl);SLprint(sl);   //3 4//SLInsert(&sl, 0, 100);//SLprint(sl); //100 1 2 3 4//SLInsert(&sl, sl.size, 200);//SLprint(sl); //100 1 2 3 4 200//SLInsert(&sl, 100, 300);//SLprint(sl);//SLErase(&sl, 0);//SLprint(sl);  //2 3 4//SLErase(&sl, sl.size - 1);//SLErase(&sl, 1);//SLprint(sl);//1 3 4
}int main()
{slTest01();return 0;
}

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

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

相关文章

Linux如何查看端口是否占用

在Linux中&#xff0c;有多种方法可以用来检查端口是否被占用。以下是一些常用的命令&#xff1a; netstat&#xff1a;这是一个非常通用的命令&#xff0c;可以用来查看所有端口的使用情况。如果你想查找特定的端口是否被占用&#xff0c;可以使用netstat命令配合grep。例如&…

【MySQL】DQL

DQL&#xff08;数据查询语言&#xff09;用于在MySQL数据库中执行数据查询操作。它主要包括SELECT语句&#xff0c;用于从表中检索数据。 0. 基本语法 SELECT 字段列表 FROM 表名列表 WHERE 条件列表 GROUP BY 分组字段列表 HAVING 分组后条件列表 ORDER BY 排序字段列表 …

【市工信】2024年青岛市绿色工厂、绿色工业园区等绿色制造示范申报

科大睿智小编从青岛市工信局了解到&#xff0c;为深入贯彻绿色发展理念&#xff0c;牢固树立绿色低碳发展导向&#xff0c;进一步完善绿色制造体系&#xff0c;培育绿色制造先进典型&#xff0c;根据《工业和信息化部关于印发<绿色工厂梯度培育及管理暂行办法>的通知》&a…

springcloud:3.1介绍雪崩和Resilience4j

灾难性雪崩效应 简介 服务与服务之间的依赖性,故障会传播,造成连锁反应,会对整个微服务系统造成灾难性的严重后果,这就是服务故障的“雪崩”效应。 原因 1.服务提供者不可用(硬件故障、程序bug、缓存击穿、用户大量请求) 2.重试加大流量(用户重试,代码逻辑重试) 3.服…

在golang中使用protoc

【Golang】proto生成go的相关文件 推荐个人主页&#xff1a;席万里的个人空间 文章目录 【Golang】proto生成go的相关文件1、查看proto的版本号2、安装protoc-gen-go和protoc-gen-go-grpc3、生成protobuff以及grpc的文件 1、查看proto的版本号 protoc --version2、安装protoc-…

Acwing 周赛132 解题报告 | 珂学家 | 并查集 + floyd寻路

前言 整体评价 A. 大小写转换 Q: 把字符串s统一成小写字母形态 题型&#xff1a;签到 知识点: 考察字符串的API题 c可以借助transform函数&#xff0c;进行转化 #include <bits/stdc.h>using namespace std;int main() {string s;cin >> s;// 把自己转化为小写…

10-Java装饰器模式 ( Decorator Pattern )

Java装饰器模式 摘要实现范例 装饰器模式&#xff08;Decorator Pattern&#xff09;允许向一个现有的对象添加新的功能&#xff0c;同时又不改变其结构 装饰器模式创建了一个装饰类&#xff0c;用来包装原有的类&#xff0c;并在保持类方法签名完整性的前提下&#xff0c;提供…

陶瓷工业5G智能制造工厂数字孪生可视化平台,推进行业数字化转型

陶瓷工业5G智能制造工厂数字孪生可视化平台&#xff0c;推进行业数字化转型。在陶瓷工业领域&#xff0c;5G智能制造工厂数字孪生可视化平台的应用正在改变着行业的传统生产模式&#xff0c;推动着数字化转型的进程。本文将围绕这一主题展开探讨&#xff0c;分析数字孪生可视化…

配置之道:深入研究Netty中的Option选项

欢迎来到我的博客&#xff0c;代码的世界里&#xff0c;每一行都是一个故事 配置之道&#xff1a;深入研究Netty中的Option选项 前言Option的基础概念ChannelOption与Bootstrap Option常见的ChannelOption类型ChannelConfig的使用Option的生命周期不同传输协议的Option 前言 在…

Tomcat部署Web服务器及基础功能配置

前言 Tomcat作为一款网站服务器&#xff0c;目前市面上Java程序使用的比较多&#xff0c;作为运维工人&#xff0c;有必要了解一款如何去运行Java环境的网站服务。 目录 一、Java相关介绍 1. Java历史 2. Java跨平台服务 3. Java实现动态网页功能 3.1 servelt 3.2 jsp …

Revit-二开之创建TextNote-(1)

Revit二开之创建TextNote TextNode在Revit注释模块中&#xff0c;具体位置如图所示 图中是Revit2018版本 【Revit中的使用】 Revit 中的操作是点击上图中的按钮在平面视图中点击任意放置放置就行&#xff0c; 在属性中可以修改文字 代码实现 创建TextNode ExternalComm…

Web Tomcat

目录 1 前言2 Tomcat的安装3 Tomcat文件的构成4 Tomcat的使用步骤 1 前言 Tomcat是一个 http(web)的容器&#xff0c;笼统的理解一下所有的网站都叫做web。这个web容器可以把我们的前端(htmlcssjs)和后端(servlet)代码都运行起来。 Tomcat是一个免费的开源的Servlet容器&#…

Flutter中的三棵树

Widget Tree&#xff1a; 页面配置信息。 Element Tree&#xff1a; Widget tree的实例化对象&#xff0c;创建出renderObject&#xff0c;并关联到element.renderobject属性上&#xff0c;最后完成RenderObject Tree的创建。 RenderObject Tree&#xff1a;完成布局和图层绘制…

【嵌入式学习】网络编程day03.02

一、项目 1、TCP机械臂测试 #include <myhead.h> #define SER_IP "192.168.126.32" #define SER_PORT 8888 #define CER_IP "192.168.126.42" #define CER_PORT 9891 int main(int argc, const char *argv[]) {int wfd-1;//创建套接字if((wfdsocke…

《TCP/IP详解 卷一》第8章 ICMPv4 和 ICMPv6

目录 8.1 引言 8.1.1 在IPv4和IPv6中的封装 8.2 ICMP 报文 8.2.1 ICMPv4 报文 8.2.2 ICMPv6 报文 8.2.3 处理ICMP报文 8.3 ICMP差错报文 8.3.1 扩展的ICMP和多部报文 8.3.2 目的不可达和数据包太大 8.3.3 重定向 8.3.4 ICMP 超时 8.3.5 参数问题 8.4 ICMP查询/信息…

划分开始结束位置设置标记

划分开始结束位置 初始音轨如下图所示 在想开始地方单击左键&#xff0c;长按直到你想要的结束位置松开。就可以划分开始和结束位置 设置标记 方式1 &#xff1a;直接点击该图标 方式二&#xff1a;使用快捷键M 设置标记点可以自定义名称方便检索标记点

javaWebssh酒店客房管理系统myeclipse开发mysql数据库MVC模式java编程计算机网页设计

一、源码特点 java ssh酒店客房管理系统是一套完善的web设计系统&#xff08;系统采用ssh框架进行设计开发&#xff09;&#xff0c;对理解JSP java编程开发语言有帮助&#xff0c;系统具有完整的源代码和数据库&#xff0c;系统主要采用B/S模式开发。开发环境为TOMCAT7.0…

STL容器之string类

文章目录 STL容器之string类1、 什么是STL2、STL的六大组件3、string类3.1、string类介绍3.2、string类的常用接口说明3.2.1、string类对象的常见构造3.2.2、string类对象的容量操作3.2.3、string类对象的访问及遍历操作3.2.4、 string类对象的修改操作3.2.5、 string类非成员函…

车辆维护和燃油里程跟踪器LubeLogger

什么是 LubeLogger &#xff1f; LubeLogger 是一个自托管、开源、基于网络的车辆维护和燃油里程跟踪器。 LubeLogger 比较适合用来跟踪管理您的汽车的维修、保养、加油的历史记录&#xff0c;比用 Excel 强多了 官方提供了在线试用&#xff0c;可以使用用户名 test 和密码 123…

机器学习-4

文章目录 前言数组创建切片索引索引遍历切片编程练习 总结 前言 本篇将介绍数据处理 Numpy 库的一些基本使用技巧&#xff0c;主要内容包括 Numpy 数组的创建、切片与索引、基本运算、堆叠等等。 数组创建 在 Python 中创建数组有许多的方法&#xff0c;这里我们使用 Numpy 中…