【040】巧妙地穿梭双端:掌握C++ STL中deque容器的强大功能

news2024/11/25 12:46:47

巧妙地穿梭双端:掌握C++ STL中deque容器的强大功能

  • 引言
  • 一、deque容器概述
  • 二、deque容器实现原理
  • 三、deque容器常用API
    • 3.1、deque的构造函数
    • 3.2、deque的赋值操作
    • 3.3、deque的大小操作
    • 3.4、deque的双端插入和删除操作
    • 3.5、deque的数据存取
    • 3.6、deque的插入操作
    • 3.7、deque的删除操作
  • 四、deque容器在竞技类中的应用案例
  • 总结

引言


💡 作者简介:一个热爱分享高性能服务器后台开发知识的博主,目标是通过理论与代码实践的结合,让世界上看似难以掌握的技术变得易于理解与掌握。技能涵盖了多个领域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、协程、DPDK等。
👉
🎖️ CSDN实力新星、CSDN博客专家
👉
🔔 专栏介绍:从零到c++精通的学习之路。内容包括C++基础编程、中级编程、高级编程;掌握各个知识点。
👉
🔔 专栏地址:C++从零开始到精通
👉
🔔 博客主页:https://blog.csdn.net/Long_xu


🔔 上一篇:【039】掌握Vector容器:C++中最强大的动态数组

一、deque容器概述

deque(双端队列)是C++ STL(Standard Template Library)中的一个容器,它提供了高效的插入和删除操作,并且支持在两端进行快速访问的能力。

与vector相比,deque具有更好的插入和删除性能,尤其是在容器的前端。这是因为deque在内部实现上采用了一块连续的存储区,并结合了多个缓冲区,使得插入和删除操作能够在任意位置进行,而不会导致整个容器的元素移动。

Vector容器是单向开口的连续内存空间,deque则是一种双向开口的连续线性空间。所谓的双向开口,意思是可以在头尾两端分别做元素的插入和删除操作,当然,vector容器也可以在头尾两端插入元素,但是在其头部操作效率奇差,无法被接受。

在这里插入图片描述

deque还具备以下特点:

  1. 双向访问:deque允许高效地在队首和队尾执行插入、删除和访问操作,无论容器的大小如何。
  2. 动态扩展:deque可以根据需要自动调整内部的缓冲区大小,因此可以灵活地适应不同的数据规模。
  3. 随机访问:类似于数组和vector,deque支持通过索引快速访问特定位置的元素。
  4. 迭代器失效:插入和删除操作可能会导致迭代器失效,因此在使用迭代器时需要格外小心。

使用deque时,可以利用其快速插入和删除的特性处理大量数据或者需要频繁在两端操作的场景。相比其他容器,deque提供了更加灵活和高效的元素管理,并且可以根据需要动态调整内部的存储空间。

要使用deque容器,需要包含头文件<deque>,并使用std命名空间或者使用using namespace std;进行简化操作。

Deque容器和vector容器最大的差异:

  • 一在于deque允许使用常数项时间对头端进行元素的插入和删除操作。
  • 二在于deque没有容量的概念,因为它是动态的以分段连续空间组合而成,随时可以增加一段新的空间并链接起来,换句话说,像vector那样,"I旧空间不足而重新配置一块更大空间,然后复制元素,再释放旧空间’这样的事情在deque身上是不会发生的。也因此,deque没有必须要提供所谓的空间保留(reserve)功能.虽然deque容器也提供了Random Access lterator,但是它的迭代器并不是普通的指针,其复杂度和vector不是一个量级,这当然影响各个运算的层面。因此,除非有必要,我们应该尽可能的使用vector,而不是deque。

对deque进行的排序操作,为了最高效率,可将deque先完整的复制到一个vector中,对vector容器进行排序,再复制回deque。

二、deque容器实现原理

Deque容器是连续的空间,至少逻辑上看来如此,连续现行空间总是令我们联想到array和vector,array无法成长,vector虽可成长却只能向尾端成长,而且其成长其实是一个假象,事实上(1)申请更大空间(⑵)原数据复制新空间(⑶释放原空间三步骤,如果不是vector每次配置新的空间时都留有余裕,其成长假象所带来的代价是非常昂贵的。

Deque是由一段一段的定量的连续空间构成。一旦有必要在deque前端或者尾端增加新的空间,便配置一段连续定量的空间,串接在deque的头端或者尾端。Deque最大的工作就是维护这些分段连续的内存空间的整体性的假象,并提供随机存取的接口,避开了重新配置空间,复制,释放的轮回,代价就是复杂的迭代器架构。既然deque是分段连续内存空间,那么就必须有中央控制,维持整体连续的假象,数据结构的设计及迭代器的前进后退操作颇为繁琐。

Deque代码的实现远比vector或list都多得多。Deque采取一块所谓的map(注意,不是STL的map容器)作为主控,这里所谓的 map是一小块连续的内存空间,其中每一个元素(此处成为一个结点)都是一个指针,指向另一段连续性内存空间,称作缓冲区。缓冲区才是deque的存储空间的主体。

deque(双端队列)在C++ STL中的实现原理如下:

  1. 内存结构:deque使用了一块连续的存储区,其中每个元素被称为缓冲区(buffer)。每个缓冲区都是固定大小的,并且包含多个节点(node),每个节点存储一个元素。

  2. 头尾迭代器:deque维护了两个迭代器,即头部迭代器(begin)和尾部迭代器(end)。这两个迭代器指向不同的缓冲区,并用于访问deque的首元素和尾元素。

  3. 缓冲区管理:deque采用了一个索引表(map)来记录缓冲区的位置和大小。索引表中每个元素都指向一个缓冲区,并保存了该缓冲区的起始位置、容量以及节点数。

  4. 增长策略:当需要在deque的前端或后端插入新元素时,deque会根据以下策略进行内存增长:

    • 当前端空间不足时,在头部添加一个新的缓冲区,并更新索引表。
    • 当后端空间不足时,在尾部添加一个新的缓冲区,并更新索引表。
    • 如果之前已经分配过一块较大的缓冲区,且其剩余空间足够容纳新元素,则会在该缓冲区中直接插入。
  5. 缓冲区大小:对于deque的每个缓冲区,其节点数目通常为2的幂次方。这是因为使用二进制位来表示节点索引可以通过位运算实现快速的计算。

通过上述机制,deque实现了在两端进行高效的插入和删除操作。当插入或删除操作导致需要添加或移除缓冲区时,deque会根据增长策略进行适当的内存调整,并更新索引表以保持deque的整体结构有效。

注意:由于deque允许在任意位置进行插入和删除操作,而不仅限于头部和尾部,因此迭代器的失效情况相对复杂一些,需要格外注意使用迭代器的情况。
在这里插入图片描述

三、deque容器常用API

3.1、deque的构造函数

在C++中,deque(双端队列)的构造函数原型如下:

  1. 默认构造函数:

    deque();
    

    该构造函数创建一个空的deque对象。

  2. 带有初始元素和默认值的构造函数:

    deque(size_type count, const T& value = T());
    

    该构造函数创建一个包含count个元素的deque对象,并将每个元素初始化为value。

  3. 带有初始元素范围的构造函数:

    template <class InputIterator>
    deque(InputIterator first, InputIterator last);
    

    该构造函数创建一个包含范围在[first, last)之间的元素的deque对象。参数first和last可以是指向序列的迭代器。

  4. 拷贝构造函数:

    deque(const deque& other);
    

    该构造函数创建一个与其他deque对象相同的副本。

  5. 移动构造函数:

    deque(deque&& other) noexcept;
    

    该构造函数创建一个新的deque对象,通过移动其他deque对象的内容。

使用示例:

  1. 使用默认构造函数创建空的deque:

    deque<int> myDeque; // 创建一个空的deque对象
    
  2. 使用带有初始元素和默认值的构造函数创建具有特定大小和初始值的deque:

    deque<int> myDeque(5, 10); // 创建一个包含5个元素,每个元素初始化为10的deque对象
    
  3. 使用带有初始元素范围的构造函数创建deque:

    vector<int> vec = {1, 2, 3, 4, 5};
    deque<int> myDeque(vec.begin(), vec.end()); // 根据vector的内容创建一个相应的deque对象
    
  4. 使用拷贝构造函数创建副本:

    deque<int> originalDeque = {1, 2, 3};
    deque<int> copiedDeque(originalDeque); // 创建一个originalDeque的副本
    
  5. 使用移动构造函数:

    deque<int> tempDeque {1, 2, 3, 4, 5};
    deque<int> movedDeque(std::move(tempDeque));  // 移动tempDeque创建一个新的deque
    

3.2、deque的赋值操作

  1. assign() 函数原型:

    void assign(size_type count, const T& value);
    template<class InputIt>
    void assign(InputIt first, InputIt last);
    
  2. = (拷贝赋值运算符)函数原型:

    deque& operator=(const deque& other);
    
  3. swap() 函数原型:

    void swap(deque& other) noexcept;
    

使用示例:

  1. assign() 示例:

    #include <iostream>
    #include <deque>
    
    int main() {
        std::deque<int> myDeque;
        
        // 使用 assign 为 deque 赋值
        myDeque.assign(5, 42);  // 将5个值为42的元素赋给 deque
        
        // 输出 deque 的内容:42, 42, 42, 42, 42
        for (const auto& element : myDeque) {
            std::cout << element << " ";
        }
        std::cout << std::endl;
        
        return 0;
    }
    
  2. =(拷贝赋值运算符)示例:

    #include <iostream>
    #include <deque>
    
    int main() {
        std::deque<int> deque1 {1, 2, 3};
        std::deque<int> deque2 {4, 5, 6};
        
        deque2 = deque1;  // 将deque1拷贝给deque2
        
        // 输出 deque2 的内容:1, 2, 3
        for (const auto& element : deque2) {
            std::cout << element << " ";
        }
        std::cout << std::endl;
        
        return 0;
    }
    
  3. swap() 示例:

    #include <iostream>
    #include <deque>
    
    int main() {
        std::deque<int> deque1 {1, 2, 3};
        std::deque<int> deque2 {4, 5, 6};
        
        deque1.swap(deque2);  // 交换 deque1 和 deque2 的内容
        
        // 输出 deque1 的内容:4, 5, 6
        for (const auto& element : deque1) {
            std::cout << element << " ";
        }
        std::cout << std::endl;
        
        return 0;
    

3.3、deque的大小操作

C++ deque(双端队列)提供了一些函数来获取和修改队列的大小。以下是deque大小操作的函数原型和使用示例:

  1. size() 函数:

    • 函数原型:size_type size() const noexcept;
    • 功能:返回deque中元素的数量。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          size_t size = myDeque.size();
          
          // 输出deque的大小:5
          std::cout << "Size of deque: " << size << std::endl;
          
          return 0;
      }
      
  2. empty() 函数:

    • 函数原型:bool empty() const noexcept;
    • 功能:检查deque是否为空。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque;
          
          if (myDeque.empty()) {
              std::cout << "Deque is empty." << std::endl;
          } else {
              std::cout << "Deque is not empty." << std::endl;
          }
          
          return 0;
      }
      
  3. resize() 函数:

    • 函数原型:void resize(size_type count);
      void resize(size_type count, const value_type& value);
    • 功能:调整deque的大小为指定的数量。如果新的大小比当前大小大,则在末尾插入默认的或指定的值;如果新的大小比当前大小小,则删除末尾的元素。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          myDeque.resize(8);  // 将deque的大小调整为8,新增的元素使用默认值0填充
          
          // 输出调整后的deque:1, 2, 3, 4, 5, 0, 0, 0
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          std::cout << std::endl;
          
          return 0;
      }
      

3.4、deque的双端插入和删除操作

C++ deque(双端队列)提供了一些函数来进行双端插入和删除操作。

  1. push_front() 函数:

    • 函数原型:void push_front(const T& value);
    • 功能:在deque的前端插入一个元素。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {2, 3, 4};
          
          myDeque.push_front(1);  // 在deque的前端插入元素1
          
          // 输出调整后的deque:1, 2, 3, 4
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          std::cout << std::endl;
          
          return 0;
      }
      
  2. pop_front() 函数:

    • 函数原型:void pop_front();
    • 功能:从deque的前端删除一个元素。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          myDeque.pop_front();  // 删除deque的第一个元素
          
          // 输出调整后的deque:2, 3, 4, 5
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          std::cout << std::endl;
          
          return 0;
      }
      
  3. push_back() 函数:

    • 函数原型:void push_back(const T& value);
    • 功能:在deque的末尾插入一个元素。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3};
          
          myDeque.push_back(4);  // 在deque的末尾插入元素4
          
          // 输出调整后的deque:1, 2, 3, 4
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          std::cout << std::endl;
          
          return 0;
      }
      
  4. pop_back() 函数:

    • 函数原型:void pop_back();
    • 功能:从deque的末尾删除一个元素。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          myDeque.pop_back();  // 删除deque的最后一个元素
          
          // 输出调整后的deque:1, 2, 3, 4
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          std::cout << std::endl;
          
          return 0;
      }
      

3.5、deque的数据存取

C++ deque(双端队列)提供了一些函数来进行数据的存取操作。

  1. at() 函数:

    • 函数原型:T& at(size_t pos);
    • 功能:返回指定位置(pos)的元素的引用,并进行边界检查。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 访问第三个元素(下标为2)
          int element = myDeque.at(2);
          
          std::cout << "Element at index 2: " << element << std::endl;
          
          return 0;
      }
      
  2. operator[] 运算符重载:

    • 函数原型:T& operator[](size_t pos);
    • 功能:返回指定位置(pos)的元素的引用,不进行边界检查。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 访问第四个元素(下标为3)
          int element = myDeque[3];
          
          std::cout << "Element at index 3: " << element << std::endl;
          
          return 0;
      }
      
  3. front() 函数:

    • 函数原型:T& front();
    • 功能:返回deque的第一个元素的引用。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 访问第一个元素
          int firstElement = myDeque.front();
          
          std::cout << "First element: " << firstElement << std::endl;
          
          return 0;
      }
      
  4. back() 函数:

    • 函数原型:T& back();
    • 功能:返回deque的最后一个元素的引用。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 访问最后一个元素
          int lastElement = myDeque.back();
          
          std::cout << "Last element: " << lastElement << std::endl;
          
          return 0;
      }
      

通过这些函数可以访问deque中指定位置的元素,或者获取deque的第一个和最后一个元素的值。请注意,在使用下标运算符 [] 访问元素时,不进行边界检查,因此确保在合法的索引范围内进行访问,以避免访问超出deque的边界导致未定义行为。

3.6、deque的插入操作

C++ deque的插入操作函数insert()提供了多种重载形式,可以在指定位置插入一个或多个元素。

  1. insert() 函数(单个元素插入):

    • 函数原型:iterator insert(iterator pos, const T& value);
    • 功能:在位置pos之前插入单个元素value,返回一个指向新插入元素的迭代器。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 4, 5};
          
          // 在第三个位置之前插入元素
          auto it = myDeque.insert(myDeque.begin() + 2, 3);
          
          // 打印插入后的deque
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          
          return 0;
      }
      
  2. insert() 函数(多个元素插入):

    • 函数原型:iterator insert(iterator pos, InputIt first, InputIt last);
    • 功能:在位置pos之前插入来自范围 [first, last) 的元素,返回一个指向第一个新插入元素的迭代器。
    • 示例:
      #include <iostream>
      #include <deque>
      #include <vector>
      
      int main() {
          std::deque<int> myDeque {1, 2, 5};
          std::vector<int> values {3, 4};
          
          // 在第三个位置之前插入两个元素
          auto it = myDeque.insert(myDeque.begin() + 2, values.begin(), values.end());
          
          // 打印插入后的deque
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          
          return 0;
      }
      

通过这些insert()函数的不同形式,可以在deque的指定位置插入一个或多个元素。使用单个元素插入形式可以方便地插入一个元素,而使用多个元素插入形式可以直接将一个范围内的元素插入到deque中。无论是单个元素还是多个元素插入,insert()都返回一个指向新插入元素的迭代器,方便对插入结果进行进一步操作。

3.7、deque的删除操作

C++ deque的删除操作函数包括clear()erase(),它们可以用于删除deque中的元素。

  1. clear() 函数:

    • 函数原型:void clear();
    • 功能:清空deque中的所有元素,使其变为空deque。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 清空deque
          myDeque.clear();
          
          // 打印清空后的deque大小
          std::cout << "Size of deque after clearing: " << myDeque.size() << std::endl;
          
          return 0;
      }
      
  2. erase() 函数(单个元素删除):

    • 函数原型:iterator erase(iterator pos);
    • 功能:删除位置pos处的元素,并返回指向被删除元素之后的元素的迭代器。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 删除第三个位置处的元素
          auto it = myDeque.erase(myDeque.begin() + 2);
          
          // 打印删除后的deque
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          
          return 0;
      }
      
  3. erase() 函数(范围删除):

    • 函数原型:iterator erase(iterator first, iterator last);
    • 功能:删除从位置firstlast之间的元素(不包括last),并返回指向被删除元素之后的元素的迭代器。
    • 示例:
      #include <iostream>
      #include <deque>
      
      int main() {
          std::deque<int> myDeque {1, 2, 3, 4, 5};
          
          // 删除第二个位置到第四个位置之间的元素
          auto it = myDeque.erase(myDeque.begin() + 1, myDeque.begin() + 4);
          
          // 打印删除后的deque
          for (const auto& element : myDeque) {
              std::cout << element << " ";
          }
          
          return 0;
      }
      

通过使用clear()函数,可以快速清空整个deque。而使用erase()函数,可以删除一个或多个元素,无论是单个元素还是范围内的元素。在删除操作完成后,这些函数都提供了一个返回值,指示了删除后的新迭代器位置,方便对结果进行进一步操作。

四、deque容器在竞技类中的应用案例

假设有5名选手:选手ABCDE,10个评委分别对每一名选手打分,去除最高分,去除评委中最低分,取平均分。

代码示例:

#include <iostream>
#include <deque>
#include <algorithm> // 用于排序

int main() {
    // 创建选手名单和评委打分的deque
    std::deque<char> players {'A', 'B', 'C', 'D', 'E'};
    std::deque<int> scores;
    
    // 让每个评委为每位选手打分,共10个评委
    for (int i = 0; i < 10; i++) {
        // 在1到10之间生成随机得分(假设当前选手得分均为整数)
        int score = rand() % 10 + 1;
        scores.push_back(score);
    }
    
    // 对评委得分进行排序
    std::sort(scores.begin(), scores.end());
    
    // 去除最高分和最低分
    scores.pop_back(); // 去除最高分
    scores.pop_front(); // 去除最低分
    
    // 计算平均分
    double average = 0.0;
    for (const auto& score : scores) {
        average += score;
    }
    average /= scores.size();
    
    // 打印结果
    std::cout << "选手:" << players.front() << std::endl;
    std::cout << "平均分:" << average << std::endl;
    
    return 0;
}

总结

在本文中,深入探讨了C++标准模板库(STL)中的deque容器,并展示了它的强大功能。deque是一个双端队列,可以在两端高效地进行元素的插入和删除操作。

首先,介绍了deque的基本特点和使用方法。与vector相比,deque具有更好的插入和删除性能,因为它采用了分段连续存储的方式。这使得在队列的前端和后端执行插入和删除操作效率都很高,且不会导致内存重新分配。

其次,讨论了deque的迭代器和遍历方式。deque提供了双向迭代器,可以方便地在容器的任意位置进行元素的访问和修改。我们还展示了如何使用范围-for循环来遍历deque中的元素,并通过迭代器的逆序遍历实现了从尾部到头部的遍历。

接下来,着重介绍了deque的一些高级功能。例如,使用push_front()push_back()函数可以在deque的前端和后端插入元素,而pop_front()pop_back()函数则分别删除deque的第一个和最后一个元素。我们还展示了如何使用emplace()emplace_back()函数来进行原地构造,并介绍了与deque相关的排序算法。

此外,由于deque的元素可能被分散存储在多个内存块中,为了减少指针引起的额外开销,可以使用指定一个特定的缓冲区大小,并调用shrink_to_fit()函数来优化存储空间。

最后,通过一个实际案例展示了deque的应用场景。以选手打分为例,我们使用deque容器实现了对选手的评分汇总,并通过去除最高分和最低分来计算平均分。这个案例不仅演示了deque的双端操作特性,还展示了它在实际问题中的灵活运用。

在这里插入图片描述

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

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

相关文章

Spring IOC AOP

IOC容器 概念 IOC&#xff0c;全程Inversion of Control&#xff08;控制反转&#xff09; 通过控制反转&#xff08;创建对象的权限交给框架&#xff0c;所以叫反转&#xff09;创建的对象被称为Spring Bean&#xff0c;这个Bean和用new创建出来的对象是没有任何区别的。 官…

排序算法第三辑——交换排序

目录 ​编辑 一&#xff0c;交换排序算法的简介 二&#xff0c;冒泡排序 冒泡排序代码&#xff1a;排升序 三&#xff0c;快速排序 1.霍尔大佬写的快速排序 2.挖坑法 3.前后指针法 四&#xff0c;以上代码的缺陷与改正方法 三数取中 三路划分&#xff1a; 五&#…

真的绝了,通过注释来埋点好简单!!

目录 回顾 开始 插件编写 功能一 功能二 功能三 合并功能 运行代码 总结 这篇文章主要讲如何根据注释&#xff0c;通过babel插件自动地&#xff0c;给相应函数插入埋点代码&#xff0c;在实现埋点逻辑和业务逻辑分离的基础上&#xff0c;配置更加灵活 回顾 上篇文章…

微服务系列文章之 Springboot应用在k8s集群中配置的使用

Docker部署其实也可以再docker run或者dockerfile里面&#xff0c;将配置文件目录映射到宿主机&#xff0c;然后通过宿主机配置文件修改参数。 FROM docker.io/python:3.6MAINTAINER tianye # 设置容器时间 RUN cp /usr/share/zoneinfo/Asia/Shanghai /etc/localtime &&am…

Windows安装Oh-My-Posh美化Powershell

Windows Terminal&#xff1a;https://www.microsoft.com/store/productId/9N0DX20HK701 最新Powershell下载&#xff1a;https://github.com/PowerShell/PowerShell/releases Oh-My-Posh官网&#xff1a;https://ohmyposh.dev/ Nerd字体下载&#xff1a;https://www.nerdfonts…

Git源代码管理方案

背景 现阶段的Git源代码管理上有一些漏洞&#xff0c;导致在每次上线发布的时间长、出问题&#xff0c;对整体产品的进度有一定的影响。 作用 新的Git源代码管理方案有以下作用&#xff1a; 多功能并行开发时&#xff0c;测试人员可以根据需求任务分配测试自己的功能&#…

MyBatis-Plus条件查询问题解决

问题描述 系统中有用户注册的功能&#xff0c;但是会出现重复注册的现象&#xff0c;代码中有做过重复校验&#xff0c;但是没有生效。 问题解决 首先排查数据生成时间点不同&#xff0c;相差时间有长有短&#xff0c;不是用户同时多次点击的原因&#xff0c;应该是用户这边…

js判断两个数组是增加还是删除

JS判断两个数组的数据&#xff0c;增加的数据以及删除的数据。 // 第一个参数是新数组&#xff0c;第二个参数是旧数 const compareArrays function(arr1, arr2 ) {let remove []let add []// 旧数据循环for (let i 0; i < arr2.length; i) {let item arr2[i];if (arr…

EvilBox---One靶机复盘

EvilBox—One靶机复盘 这个靶场学会了原来id_rsa的私钥可以直接爆破&#xff0c;利用ssh2john工具提取私钥&#xff0c;然后john直接爆破就可以了。 靶场下载地址&#xff1a;https://download.vulnhub.com/evilbox/EvilBox—One.ova 这个靶场是直接给ip地址的我们就不用扫描…

Spring Boot使用httpcomponents实现http请求

基于org.apache.httpcomponents的httpclient实现&#xff0c;其它的实现方式都行。 1. pom文件 <?xml version"1.0" encoding"UTF-8"?> <project xmlns"http://maven.apache.org/POM/4.0.0"xmlns:xsi"http://www.w3.org/2001/…

快速实现主从表编辑,实现多个不定长从表

目录 1 前言 2 不定长表、定长表的定义 3 根据已有的电子表格制作数据库表并导入数据 3.1 订单 3.2 订单明细 3.3 客户 4 配置主从关联关系 5 继续增加一个主从关联关系 6 测试一下运行结果 7 一段代码用于实现在panel中画出字段列表面板 1 前言 实际工作中&#xff…

扑克牌检测Y8S

采用YOLOV8训练&#xff0c;得到PT模型&#xff0c;然后直接转ONNX&#xff0c;使用OPENCV的DNN&#xff0c;不需要其他依赖&#xff0c;支持C/PYTHON 扑克牌检测Y8S

数据结构(王道)——线性表的存储结构之顺序表

线性表和顺序表的关系&#xff1a; 两种实现方式&#xff1a;静态分配、动态分配 总结&#xff1a;

Win7如何合并C盘与D盘?

电脑C盘不够用&#xff0c;需要把D盘的卷删除并合并到C盘中。 整体步骤&#xff1a; 1.右击此电脑-管理-磁盘管理。 2.假如要把D盘容量合并到C盘&#xff0c;右击D盘&#xff0c;选择删除卷&#xff0c;点击“是”。此时D盘数据会被清空&#xff0c;建议先备份数据。 3.删除…

消息队列MQ入门理解

功能特性: 物联网应用 物联网设备通过微消息队列(LMQ)连接云端,双向通信,数据传输;设备数据通过消息队列(MQ)连接计算引擎,分析数据或者源数据实时高效写入到 HiTSDB / HiStore / ODPS 等。 大规模缓存同步 在商业大促活动中,如“双11”大促,各个分会场会有琳琅…

基于输出调节的一致性编队控制

参考博客&#xff1a; https://blog.csdn.net/weixin_44346182/article/details/131747082 在输出调节的基础上&#xff0c;实现了输出一致性&#xff0c;而编队控制就是没有偏移量的状态一致性&#xff0c;恰好本题的C矩阵就是系统的第一阶的状态&#xff08;位置&#xff0…

spring boot security自定义权限检查

前言 鉴权主要分为身份认证和权限控制两部分&#xff1a; 身份认证&#xff1a;检查当前用户是否合法&#xff08;比如已登录&#xff09; 权限控制&#xff1a;检查当前用户是否有访问该资源的权限 本文主要给出一个示例&#xff0c;说明如何自定义权限控制。 因为一个完整的…

增长能力模型:最大限度地发挥增长团队的潜力

作为增长领导者&#xff0c;准确评估你的组织和团队成员是一项非常重要且耗时的工作。但是如果我们计划为未来的增长领导者创造一条职业道路&#xff0c;我们就需要一个流程来为整个团队提供客观的反馈&#xff0c;这就是增长能力模型的用武之地。 增长能力模型提供了一个框架&…

argc,argv

文章目录 argc 是argument count的缩写表示传入main函数中的参数个数&#xff0c;包括这个程序本身 argv 是 argument vector的缩写表示传入main函数中的参数列表&#xff0c;其中argv[0]:程序的名字(.exe) int main(int argc, char** argv) {std::cout << "argc:…

1、环境搭建

下载visual studio,社区版基本够用了,其他版本是收费的。 下载之后安装即可。 安装完成之后要求我们选择要使用的模块。这里我们勾选如图中圈起来的模块,并选择安装。因为我这边已经安装过,所以按钮变成了“关闭” 安装完毕后,重启。 重启完成之后,打开Visual studio。…