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

C++——list容器以及手动实现

LIST容器

  • list概述
    • 列表
    • 容器属性
    • 例子
  • list函数
    • 构造函数
      • 默认构造函数:
      • 带有元素个数和元素初值的构造函数:
      • 范围构造函数:
      • 拷贝构造函数:
      • 移动构造函数:
      • 示例
    • 赋值运算符重载
      • 拷贝赋值操作符 (1):
      • 移动赋值操作符 (2):
      • 初始化列表赋值操作符 (3):
      • 示例
      • 注意事项
    • 迭代器函数
    • 插入和删除函数
    • 清空和删除函数
  • 自己实现的list容器案例

list概述

std::list

template < class T, class Alloc = allocator<T> > class list;

列表

列表是序列容器,允许在序列中的任何位置执行恒定时间插入和擦除操作,并在两个方向上进行迭代。

列表容器以双向链表的形式实现;双向链表可以将它们包含的每个元素存储在不同且不相关的存储位置。排序是通过与每个元素的关联在内部保持的,该关联链接到它前面的元素,以及与它后面的元素的链接。

它们与 forward_list 非常相似:主要区别在于forward_list对象是单链表,因此它们只能向前迭代,以换取更小、更高效的性能。

与其他基本标准序列容器(数组、向量和 deque)相比,列表在插入、提取和移动已获得迭代器的容器内的任何位置的元素方面通常表现更好,因此在大量使用这些元素的算法(如排序算法)中也是如此。

与这些其他序列容器相比,列表s 和 forward_lists 的主要缺点是它们无法通过其位置直接访问元素;例如,要访问列表中的第六个元素,必须从已知位置(如开始或结束)迭代到该位置,这需要它们之间的线性时间。它们还会消耗一些额外的内存,以保持与每个元素关联的链接信息(这可能是小型元素的大型列表的一个重要因素)。

容器属性

序列

序列容器中的元素按严格的线性顺序排序。各个元素通过它们在此序列中的位置进行访问。

双向链表

每个元素都保留有关如何定位下一个和上一个元素的信息,允许在特定元素(甚至整个范围)之前或之后进行恒定时间插入和擦除操作,但不能直接随机访问。

分配器感知

容器使用分配器对象来动态处理其存储需求。

模板参数

T

元素的类型

别名为成员类型 list::value_type。

分配

用于定义存储分配模型的分配器对象的类型。默认情况下,使用分配器类模板,该模板定义了最简单的内存分配模型,并且与值无关。

别名为成员类型 list::allocator_type。

例子

std::list 是 C++ 标准库中的双向链表(doubly linked list)容器,它提供了高效的插入和删除操作,但不支持随机访问元素。下面简要介绍一下 std::list 的底层实现机制和一个简单的示例。

底层实现机制

std::list 使用双向链表作为其底层数据结构,每个节点(node)包含两个指针:一个指向前一个节点,一个指向后一个节点。这种结构使得在任意位置插入和删除操作都很高效,因为只需要调整相邻节点的指针即可,不需要像数组那样移动大量元素。

双向链表的结构如下所示

nullptr <-> Node1 <-> Node2 <-> … <-> NodeN <-> nullptr
其中 nullptr 表示空指针,用来表示链表的头尾。每个节点中会存储实际的数据,比如 int、char、struct 等。

示例

下面是一个简单的示例展示如何使用 std::list 容器:

#include <iostream>
#include <list>int main() {// 创建一个空的 std::list 容器std::list<int> mylist;// 向 list 中插入元素mylist.push_back(1);    // {1}mylist.push_back(2);    // {1, 2}mylist.push_front(3);   // {3, 1, 2}mylist.push_back(4);    // {3, 1, 2, 4}// 使用迭代器遍历输出 list 中的元素std::cout << "List elements: ";for (auto it = mylist.begin(); it != mylist.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;// 在指定位置插入元素auto it = ++mylist.begin(); // 获取第二个元素的迭代器mylist.insert(it, 5); // 在第二个元素后面插入 5,{3, 5, 1, 2, 4}// 删除元素mylist.pop_front(); // 删除第一个元素,{5, 1, 2, 4}mylist.pop_back();  // 删除最后一个元素,{5, 1, 2}// 输出修改后的 list 元素std::cout << "Modified List elements: ";for (auto it = mylist.begin(); it != mylist.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

示例解释

1,首先,我们创建了一个 std::list 类型的空列表 mylist。

2,使用 push_back() 和 push_front() 方法向列表中添加元素。

3,使用迭代器 begin() 和 end() 遍历输出列表中的元素。

4,使用 insert() 在指定位置插入元素。

5,使用 pop_front() 和 pop_back() 方法删除第一个和最后一个元素。

6,最后,再次使用迭代器遍历输出修改后的列表元素。

这个例子展示了 std::list 容器的基本操作,包括插入、删除和遍历元素等,利用了其底层双向链表的特性,使得这些操作都能够高效地执行。

list函数

构造函数

在这里插入图片描述

std::list 的构造函数可以分为以下几类:

默认构造函数:

std::list();

创建一个空的双向链表。链表中不包含任何元素。

带有元素个数和元素初值的构造函数:

explicit std::list(size_type count, const T& value = T());

创建一个包含 count 个元素的链表,每个元素的值都是 value。例如:

std::list<int> mylist(5, 10);  // 创建一个包含5个值为10的元素的链表

范围构造函数:

template<class InputIterator>
std::list(InputIterator first, InputIterator last);

从迭代器范围 [first, last) 中构造链表,将范围内的元素复制到新建的链表中。例如:

int arr[] = {1, 2, 3, 4, 5};
std::list<int> mylist(arr, arr + 5);  // 从数组中复制元素到链表

拷贝构造函数:

std::list(const std::list& other);

使用另一个 std::list 对象 other 中的元素创建新的链表。例如:

std::list<int> original = {1, 2, 3};
std::list<int> copy = original;  // 使用拷贝构造函数创建副本

移动构造函数:

std::list(std::list&& other) noexcept;

使用另一个 std::list 对象 other 中的元素创建新的链表,并接管 other 的资源。移动构造函数通常比拷贝构造函数更高效。例如:

std::list<int> source = {1, 2, 3};
std::list<int> dest = std::move(source);  // 使用移动构造函数

示例

下面是一个综合示例,展示了 std::list 的不同构造函数的使用方式:

#include <iostream>
#include <list>int main() {// 默认构造函数创建空链表std::list<int> empty_list;// 使用带有元素个数和初值的构造函数std::list<int> filled_list(5, 10);  // 包含5个值为10的元素的链表// 使用范围构造函数int arr[] = {1, 2, 3, 4, 5};std::list<int> range_list(arr, arr + 5);  // 从数组中复制元素到链表// 使用拷贝构造函数std::list<int> original = {1, 2, 3};std::list<int> copy = original;  // 创建副本// 使用移动构造函数std::list<int> source = {4, 5, 6};std::list<int> dest = std::move(source);  // 移动构造函数// 输出链表中的元素std::cout << "Filled list elements:";for (auto& elem : filled_list) {std::cout << " " << elem;}std::cout << std::endl;std::cout << "Range list elements:";for (auto& elem : range_list) {std::cout << " " << elem;}std::cout << std::endl;std::cout << "Copy list elements:";for (auto& elem : copy) {std::cout << " " << elem;}std::cout << std::endl;std::cout << "Moved list elements:";for (auto& elem : dest) {std::cout << " " << elem;}std::cout << std::endl;return 0;

赋值运算符重载

在这里插入图片描述

拷贝赋值操作符 (1):

list& operator= (const list& x);

将另一个 std::list 对象 x 中的元素拷贝赋值给当前链表对象。例如:

std::list<int> list1 = {1, 2, 3};
std::list<int> list2 = {4, 5};list2 = list1;  // 使用拷贝赋值操作符
// 现在 list2 的元素为 {1, 2, 3}

移动赋值操作符 (2):

list& operator= (list&& x);

将另一个 std::list 对象 x 中的元素移动赋值给当前链表对象。移动赋值操作符通常用于提高效率。例如:

std::list<int> list1 = {1, 2, 3};
std::list<int> list2 = {4, 5};list2 = std::move(list1);  // 使用移动赋值操作符
// 现在 list2 的元素为 {1, 2, 3},list1 变成空链表

初始化列表赋值操作符 (3):

list& operator= (initializer_list<value_type> il);

使用初始化列表 il 中的元素来赋值给当前链表对象。例如:

std::list<int> list1 = {1, 2, 3};list1 = {4, 5, 6};  // 使用初始化列表赋值操作符
// 现在 list1 的元素为 {4, 5, 6}

示例

下面是一个综合示例,演示了 std::list 中各种赋值操作符的使用:

#include <iostream>
#include <list>int main() {// 拷贝赋值操作符示例std::list<int> list1 = {1, 2, 3};std::list<int> list2 = {4, 5};list2 = list1;  // 拷贝赋值操作符std::cout << "List2 after copy assignment:";for (auto& elem : list2) {std::cout << " " << elem;}std::cout << std::endl;// 移动赋值操作符示例std::list<int> list3 = {7, 8};std::list<int> list4 = {9, 10};list4 = std::move(list3);  // 移动赋值操作符std::cout << "List4 after move assignment:";for (auto& elem : list4) {std::cout << " " << elem;}std::cout << std::endl;// 初始化列表赋值操作符示例std::list<int> list5 = {11, 12, 13};list5 = {14, 15, 16};  // 初始化列表赋值操作符std::cout << "List5 after initializer list assignment:";for (auto& elem : list5) {std::cout << " " << elem;}std::cout << std::endl;return 0;
}

注意事项

拷贝赋值操作符和移动赋值操作符的选择通常取决于右侧操作数的类型和实际需求。

初始化列表赋值操作符用于通过大括号 {} 直接赋值一组元素。

迭代器函数

1,begin() 和 end():

iterator begin();
iterator end();
const_iterator begin() const;
const_iterator end() const;

这些函数返回链表的起始迭代器和结束迭代器。对于非常量对象,begin() 返回指向第一个元素的迭代器,end() 返回指向最后一个元素后面位置的迭代器;对于常量对象,返回的是 const_iterator,用于只读访问链表的元素。

示例

std::list<int> myList = {1, 2, 3, 4};// 使用迭代器遍历链表
for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";
}

2,rbegin() 和 rend():

reverse_iterator rbegin();
reverse_iterator rend();
const_reverse_iterator rbegin() const;
const_reverse_iterator rend() const;

这些函数返回链表的反向迭代器,用于反向遍历链表元素。rbegin() 返回指向最后一个元素的反向迭代器,rend() 返回指向第一个元素前面位置的反向迭代器;对于常量对象,返回的是 const_reverse_iterator。

示例

std::list<int> myList = {1, 2, 3, 4};// 使用反向迭代器遍历链表
for (auto rit = myList.rbegin(); rit != myList.rend(); ++rit) {std::cout << *rit << " ";
}

3,cbegin() 和 cend():

const_iterator cbegin() const noexcept;
const_iterator cend() const noexcept;

这些函数返回链表的常量迭代器,用于只读访问链表元素。cbegin() 返回指向第一个元素的常量迭代器,cend() 返回指向最后一个元素后面位置的常量迭代器。

示例

std::list<int> myList = {1, 2, 3, 4};// 使用常量迭代器遍历链表
for (auto cit = myList.cbegin(); cit != myList.cend(); ++cit) {std::cout << *cit << " ";
}

4,crbegin() 和 crend():

const_reverse_iterator crbegin() const noexcept;
const_reverse_iterator crend() const noexcept;

这些函数返回链表的常量反向迭代器,用于只读反向访问链表元素。crbegin() 返回指向最后一个元素的常量反向迭代器,crend() 返回指向第一个元素前面位置的常量反向迭代器。

示例

std::list<int> myList = {1, 2, 3, 4};// 使用常量反向迭代器遍历链表
for (auto crit = myList.crbegin(); crit != myList.crend(); ++crit) {std::cout << *crit << " ";
}

插入和删除函数

  • push_front(const T& value)
    在链表头部插入一个元素。

语法结构

void push_front(const T& value);

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};// 在链表头部插入元素myList.push_front(0); // 现在链表为 {0, 1, 2, 3}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • push_back(const T& value)
    在链表尾部插入一个元素。

语法结构

void push_back(const T& value);

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};// 在链表尾部插入元素myList.push_back(4); // 现在链表为 {1, 2, 3, 4}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • pop_front()
    删除链表头部的元素。

语法结构

void pop_front();

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};// 删除链表头部的元素myList.pop_front(); // 现在链表为 {2, 3}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • pop_back()
    删除链表尾部的元素。

语法结构

void pop_back();

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};// 删除链表尾部的元素myList.pop_back(); // 现在链表为 {1, 2}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • insert(const_iterator pos, const T& value)
    在迭代器 pos 所指位置插入元素 value。

语法结构

iterator insert(const_iterator pos, const T& value);

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};auto it = myList.begin();++it; // 移动到第二个位置// 在指定位置插入元素myList.insert(it, 4); // 现在链表为 {1, 4, 2, 3}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • erase(const_iterator pos)
    删除迭代器 pos 所指位置的元素。

语法结构

iterator erase(const_iterator pos);

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 3};auto it = myList.begin();++it; // 移动到第二个位置// 删除指定位置的元素myList.erase(it); // 现在链表为 {1, 3}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

清空和删除函数

  • clear()
    清空链表,移除所有元素。

语法结构

void clear();

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 2, 3};// 清空链表myList.clear(); // 现在链表为空std::cout << "List size after clearing: " << myList.size() << std::endl;return 0;
}
  • remove(const T& value)
    移除链表中所有等于 value 的元素。

语法结构

void remove(const T& value);

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 2, 3};// 移除所有值为 2 的元素myList.remove(2); // 现在链表为 {1, 3}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • remove_if(UnaryPredicate p)
    根据条件 p 移除符合条件的元素。

语法结构

template<class UnaryPredicate>
void remove_if(UnaryPredicate p);

示例用法

#include <iostream>
#include <list>bool isEven(int num) {return num % 2 == 0;
}int main() {std::list<int> myList = {1, 2, 3, 4, 5};// 移除所有偶数元素myList.remove_if(isEven); // 现在链表为 {1, 3, 5}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}
  • unique()
    移除链表中连续重复的元素,只保留一个。

语法结构

void unique();

示例用法

#include <iostream>
#include <list>int main() {std::list<int> myList = {1, 2, 2, 3, 3, 3, 4};// 移除连续重复的元素myList.unique(); // 现在链表为 {1, 2, 3, 4}for (auto it = myList.begin(); it != myList.end(); ++it) {std::cout << *it << " ";}std::cout << std::endl;return 0;
}

自己实现的list容器案例

namespace mylist
{// List的节点类template<class T>struct ListNode{ListNode(const T& val = T()): _pPre(nullptr), _pNext(nullptr), _val(val) {}ListNode<T>* _pPre;ListNode<T>* _pNext;T _val;};// List的迭代器类template<class T, class Ref, class Ptr>class ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;public:ListIterator(PNode pNode = nullptr): _pNode(pNode) {}ListIterator(const Self& l): _pNode(l._pNode) {}PNode Ptr() const{return _pNode;}T& operator*() const{return _pNode->_val; // 直接解引用 _pNode}T* operator->() const{return &_pNode->_val; // 直接返回 _pNode->_val 的地址}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self tem(_pNode);_pNode = _pNode->_pNext;return tem;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self operator--(int){Self tem(_pNode);_pNode = _pNode->_pPre;return tem;}bool operator!=(const Self& l) const{return _pNode != l._pNode;}bool operator==(const Self& l) const{return _pNode == l._pNode;}private:PNode _pNode;};// list类template<class T>class list{typedef ListNode<T> Node;typedef Node* PNode;public:typedef ListIterator<T, T&, T*> iterator;typedef ListIterator<T, const T&, const T&> const_iterator;public:list(){CreateHead();length = 0;}list(int n, const T& value = T()){CreateHead();length = n;while (n--){PNode tem = new Node(value); //创建 Node 对象非 PNode_pHead->_pPre->_pNext = tem;tem->_pPre = _pHead->_pPre;tem->_pNext = _pHead;_pHead->_pPre = tem;}}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){PNode tem = new Node(*first); //创建 Node 对象非 PNodefirst++;_pHead->_pPre->_pNext = tem;tem->_pPre = _pHead->_pPre;tem->_pNext = _pHead;_pHead->_pPre = tem;length++;}}list(const list<T>& l){CreateHead();PNode sta = l._pHead->_pNext;PNode end = l._pHead;while (sta != end){PNode tem = new Node(sta->_val); // 创建 Node 对象而非 PNodesta = sta->_pNext;_pHead->_pPre->_pNext = tem;tem->_pPre = _pHead->_pPre;tem->_pNext = _pHead;_pHead->_pPre = tem;length++;}}list<T>& operator=(const list<T>& l){clear(); // 使用 clear() 而不是 ~list() 来清空内容CreateHead();PNode sta = l._pHead->_pNext;PNode end = l._pHead;while (sta != end){PNode tem = new Node(sta->_val); // 创建 Node 对象而非 PNodesta = sta->_pNext;_pHead->_pPre->_pNext = tem;tem->_pPre = _pHead->_pPre;tem->_pNext = _pHead;_pHead->_pPre = tem;length++;}return *this;}~list(){clear(); // 使用 clear() 来删除所有节点delete _pHead; //删除链表头节点}///// List Iteratoriterator begin(){return iterator(_pHead->_pNext);}iterator end(){return iterator(_pHead);}const_iterator begin() const{return const_iterator(_pHead->_pNext);}const_iterator end() const{return const_iterator(_pHead);}///// List Capacitysize_t size() const{return length;}bool empty() const{return length == 0;}// List AccessT& front(){assert(!empty()); // assert(!empty())return _pHead->_pNext->_val;}const T& front() const{assert(!empty()); // assert(!empty())return _pHead->_pNext->_val;}T& back(){assert(!empty()); // assert(!empty())return _pHead->_pPre->_val;}const T& back() const{assert(!empty()); // 修改:assert(!empty())return _pHead->_pPre->_val;}// List Modifyvoid push_back(const T& val) { insert(end(), val); }void pop_back() { erase(--end()); }void push_front(const T& val) { insert(begin(), val); }void pop_front() { erase(begin()); }iterator insert(iterator pos, const T& val){assert(pos != end());PNode cur = pos.Ptr();PNode tem = new Node(val);tem->_pPre = cur->_pPre; // 修正插入节点的前驱指针tem->_pNext = cur;cur->_pPre->_pNext = tem;cur->_pPre = tem;length++;return iterator(tem);}iterator erase(iterator pos){PNode cur = pos.Ptr();cur->_pPre->_pNext = cur->_pNext;cur->_pNext->_pPre = cur->_pPre;iterator next(cur->_pNext);delete cur;length--;return next;}void clear(){PNode cur = _pHead->_pNext;while (cur != _pHead){PNode next = cur->_pNext;delete cur;cur = next;}_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;length = 0;}void swap(list<T>& l){std::swap(_pHead, l._pHead);std::swap(length, l.length);}private:void CreateHead(){_pHead = new Node;_pHead->_pNext = _pHead;_pHead->_pPre = _pHead;}PNode _pHead;size_t length;};};

相关文章:

C++——list容器以及手动实现

LIST容器 list概述列表容器属性例子 list函数构造函数默认构造函数&#xff1a;带有元素个数和元素初值的构造函数&#xff1a;范围构造函数&#xff1a;拷贝构造函数&#xff1a;移动构造函数&#xff1a;示例 赋值运算符重载拷贝赋值操作符 (1)&#xff1a;移动赋值操作符 (2…...

Win11系统文件资源管理器鼠标右键卡顿解决方法

引用链接&#xff1a; Windows 11文件资源管理器崩溃怎么解决&#xff1f;看看这7个解决办法&#xff01;...

零基础学Python之 第十八讲 文件读写

当你开始学习Python编程时&#xff0c;文件读写是一个非常基础且重要的技能。本篇博客将引导你从零开始学习如何在Python中进行文件读写操作。 1. 打开文件 在Python中&#xff0c;要操作一个文件&#xff0c;首先需要打开它。使用内置的 open() 函数来打开文件&#xff0c;语…...

检索增强生成(RAG):智能内容生成的新纪元

引言 在大 AI 时代&#xff0c;生成式人工智能&#xff08;GenAI&#xff09;模型&#xff0c;尤其是大型语言模型&#xff08;LLM&#xff09;&#xff0c;已经展现出了令人瞩目的能力。然而&#xff0c;这些模型在提供信息的准确、即时、专业、权威等方面仍存在局限。检索增…...

ubuntu2204安装elasticsearch7.17.22

下载安装 wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.22-amd64.deb wget https://artifacts.elastic.co/downloads/elasticsearch/elasticsearch-7.17.22-amd64.deb.sha512 shasum -a 512 -c elasticsearch-7.17.22-amd64.deb.sha512 su…...

介绍Servlet后端中两种接收参数方式req.getAttributer和req.getParameter的区别

数据来源 getParameter&#xff1a;此方法用于获取客户端发送的请求中携带的参数&#xff0c;通常这些参数是通过HTTP GET或POST请求传递的表单数据。例如&#xff0c;用户填写的用户名和密码等输入信息。getAttribute&#xff1a;该方法用来获取在服务器端通过setAttribute方法…...

Delphi FMX安卓Android播放mp3音频内存流

【笔记&#xff1a;安卓开发JavaDelphi FMX】 Delphi FMX跨平台的MediaPlayer无法播放音频数据流只能打开音频文件播放&#xff0c;但有时候需要直接播放内存流数据而无需生成文件&#xff0c;可以通过把内存流转ByteArray再通过Android平台系统原生的MediaDataSource或ParcelF…...

MapUtils常用方法

1、摘要 MapUtils是一个用于处理Map对象的实用工具类&#xff0c;它提供了许多方便的方法来执行常见的操作&#xff0c;如获取值、设置默认值、合并Map等。本文将介绍MapUtils的常见用法&#xff0c;以帮助你更轻松地处理Map数据。 2、前言 在Java编程中&#xff0c;Map是一…...

自定义PasswordEditText控件,在手机字体应用后,字体样式未发生改变

原来的输入类型inputType为textPassword&#xff0c;现在将 inputType删掉即可...

学习打卡第31天

...

opencascade AIS_TexturedShape源码学习 贴纹理

opencascade AIS_TexturedShape opencascade 贴纹理 前言 //! 该类允许在形状上映射纹理。 //! 显示模式 AIS_WireFrame (0) 和 AIS_Shaded (1) 的行为与 AIS_Shape 中的行为相同&#xff0c; //! 而新模式 2 (包围盒) 和 3 (纹理映射) 扩展了其功能。 //! //! 纹理本身在 (0…...

C# winform 串口读取字节流,MB级别字节流

一、串口读取字节流 在 C# 中使用 Windows Forms (WinForms) 应用程序进行串口通信时&#xff0c;通常会使用 System.IO.Ports 命名空间中的 SerialPort 类。以下是一个简单的示例&#xff0c;展示了如何设置一个串口并读取字节流。 步骤 1: 添加引用 确保你的项目中已经包含…...

创建一个简单的单链表

1.头文件的Slist.h的代码 #pragma once #include<stdio.h> #include<stdlib.h> #include<assert.h> #include<string.h> typedef int SListint; typedef struct Slist//单链表 {SListint data;struct Slist* next; }SL;//尾插 void SlistPushBank(SL*…...

15.1 Zookeeper简介安装及基础使用

1. Zookeeper介绍 1.1 介绍 1.2 应用场景简介 1.3 zookeeper工作原理 1.4 zookeeper特点...

详细说明Java中Map和Set接口的使用方法

Map与Set的基本概念与场景 Map和set是一种专门用来进行搜索的容器或者数据结构&#xff0c;其搜索的效率与其具体的实例化子类有关。以前常见的搜索方式有&#xff1a; 1. 直接遍历&#xff0c;时间复杂度为O(N)&#xff0c;元素如果比较多效率会非常慢。 2. 二分查找&#x…...

CSS3 scale 适配

Scale适配&#xff0c;在前端开发中&#xff0c;特别是在CSS3中&#xff0c;主要指的是使用scale()函数对元素进行缩放处理&#xff0c;以适应不同的屏幕尺寸或达到特定的视觉效果。以下是对Scale适配的详细介绍&#xff1a; 一、基本概念 scale() 是CSS3中transform属性的一…...

SX_初识GitLab_1

1、对GitLab的理解&#xff1a; 目前对GitLab的理解是其本质是一个远程代码托管平台&#xff0c;上面托管多个项目&#xff0c;每个项目都有一个master主分支和若干其他分支&#xff0c;远程代码能下载到本机&#xff0c;本机代码也能上传到远程平台 1.分支的作用&#xff1a…...

这才是 PHP 高性能框架 Workerman 的立命之本

大家好&#xff0c;我是码农先森。 在这个大家都崇尚高性能的时代&#xff0c;程序员的谈笑间句句都离不开高性能&#xff0c;仿佛嘴角边不挂着「高性能」三个字都会显得自己很 Low&#xff0c;其中众所皆知的 Nginx 就是高性能的代表。有些朋友可能连什么是高性能都不一定理解…...

Python——记录pip问题(解决下载慢、升级失败问题)

在python开发中&#xff0c;经常需要使用到各种各样的库。 pip又是我们常用的安装工具。但是国外的源下载速度实在太慢&#xff0c;经常导致超时。 有很多朋友刚刚学Python的时候&#xff0c;会来问为什么pip下载东西这么慢啊&#xff1f; 而且pycharm里面下载库也是非常的慢…...

Windows Server 2025 Preview 部署 Ⅰ—— ISO下载和硬件要求

目录 1. 预览版下载2. Windows 服务器的硬件要求2.1安装 Windows Server 2025 虚拟机注意事项2.2 CPU2.3 RAM / Memory2.4 存储 Storage2.5 网络 Network2.6 其他需求 1. 预览版下载 下载网站&#xff1a;https://www.microsoft.com/en-in/evalcenter/download-windows-server…...

AI2-CUDA、CuDNN、TensorRT的详细安装教程

一、查看本机的显卡 首先你要看你的电脑是否有NVIDIA的独立显卡&#xff0c;你可以在设备管理器-显示适配器中查看 点击“开始”--找到“NVIDA Control Panel” 点击帮助--系统信息--组件&#xff0c;查看NVCUDA.DLL对应的产品名称&#xff0c;就可以看住CUDA的版本号 这里的版…...

TCP连接中重复使用了两个相同的端口怎么办

1.检查并避免重复配置&#xff1a; 首先&#xff0c;应该检查系统的配置和应用程序的设置&#xff0c;确保没有错误地将多个服务或进程配置为使用相同的端口号。 使用网络监控工具&#xff08;如netstat、ss等&#xff09;来查看当前哪些端口正在被使用。 2.使用端口复用选项…...

如何自定义异常

目录 为什么自定义异常自定义异常的步骤参考资料 为什么自定义异常 自定义异常是指开发者根据应用程序的需求和逻辑&#xff0c;自行定义的异常类。与 Java 提供的标准异常类&#xff08;如 NullPointerException、IOException 等&#xff09;不同&#xff0c;自定义异常允许程…...

C++中的依赖注入

目录 1.概述 2.构造函数注入 3.setter方法注入 4.接口注入 5.依赖注入框架 6.依赖注入容器 7.依赖注入框架的工作原理 8.依赖注入的优势 9.总结 1.概述 依赖注入是一种设计模式&#xff0c;它允许我们在不直接创建对象的情况下为对象提供其依赖项&#xff1b;它通过将…...

CSS平面转换-平移

平面转换-平移 属性 transform: translate(X轴移动距离, Y轴移动距离); 取值 像素单位取值百分比&#xff08;参照盒子自身尺寸计算结果&#xff09;正负均可 技巧translate()只写一个值表示只沿着X轴移动单独设置X或Y轴距离&#xff1a;translateX()或translateY() 代码 …...

Linux-3:Shell编程——基础语法(0-50%)

目录 前言 一、变量 1.定义变量 2.使用变量 3.修改变量 4.将命令的结果赋值给变量 5.只读变量 6.删除变量 二、传递参数 三、字符串 1.字符串举例 2.统计字符串长度 3.字符串拼接 4.截取字符串 总结 前言 Shell是一种程序设计语言。作为命令语言&#xff0c;它…...

C++ --> string类模拟实现(附源码)

欢迎来到我的Blog&#xff0c;点击关注哦&#x1f495; 前言&#xff1a; C中STL扮演着极其重要的角色&#xff0c;学习C重中之重的就是学习STL&#xff0c;虽然string不作为containers的其中一员&#xff0c;但是也是值得学习的le类。下面就进行string的模拟实现 string的模拟…...

基于PHP+MySQL组合开发的微信活动投票小程序源码系统 带完整的安装代码包以及搭建部署教程

系统概述 在当今数字化时代&#xff0c;微信作为社交媒体的巨头&#xff0c;为企业和个人提供了丰富的互动营销平台。其中&#xff0c;投票活动作为一种有效的用户参与和互动方式&#xff0c;被广泛应用于各种场景。为了满足这一需求&#xff0c;我们推出了一款基于PHPMySQL组…...

利用Arcgis设置分式标注(分子分母标注)

因工作需要&#xff0c;需要设置分式标注&#xff0c;下面详细介绍下如何利用arcgis 设置分式标注&#xff0c;以下操作以供参考&#xff0c;如有疑义可提出。 一、准备工作 软件&#xff1a;arcmap 示例数据&#xff1a;行政区shp矢量图 二、操作步骤 1.添加数据 将行政区sh…...

大麦网抢票攻略:使用Python Selenium实现

随着互联网技术的发展&#xff0c;在线购票已成为人们获取演出、比赛等活动门票的主要方式。然而&#xff0c;面对热门活动&#xff0c;门票往往在开售瞬间被抢购一空。为了解决这一问题&#xff0c;本文将介绍如何利用Python和Selenium技术实现大麦网的自动抢票。 1. 环境准备…...