list使用与模拟实现

目录

list使用

reverse

sort

unique

splice

list模拟实现

类与成员函数声明

节点类型的定义

非const正向迭代器的实现

list成员函数

构造函数

尾插

头插

头删

尾删

任意位置插入

任意位置删除

清空数据

析构函数

拷贝构造函数

赋值重载函数

const迭代器的设计

终极版正向迭代器的实现

终极版反向迭代器的实现

迭代器扩充小知识


list使用

list的诸多使用与前面博客讲解的string仍然类似,我们此处只讲解比较特殊的接口函数

list的底层是带头双向循环链表,在我的数据结构专栏博客 带头双向循环链表_CSDN博客 已经讲解过了,重点是体会带头双向循环链表与顺序表的不同,尤其是某个位置插入与删除数据的效率!

reverse

void test_list1()
{list<int> lt;lt.push_back(1);lt.push_back(2);lt.push_back(3);lt.push_back(4);for (auto e : lt){cout << e << " "; //1 2 3 4 }cout << endl;lt.reverse(); //逆置链表for (auto e : lt){cout << e << " "; //4 3 2 1 }cout << endl;
}

sort

void test_list2()
{list<int> lt;lt.push_back(2);lt.push_back(3);lt.push_back(4);lt.push_back(1);for (auto e : lt){cout << e << " "; //2 3 4 1 }cout << endl;//默认是升序 < less//lt.sort(); //降序: > greatergreater<int> gt;lt.sort(gt);lt.sort(greater<int>()); //匿名对象for (auto e : lt){cout << e << " "; //4 3 2 1}cout << endl;
}

注意: list的排序无法使用算法库中的sort,主要原因是list不支持随机访问的迭代器

迭代器类型按性质或者底层实现分为三种:

1.单向:只支持++, 单链表/哈希表
2.双向:++与--都支持,双向链表/红黑树(map和set)
3.随机:++/--/+/- vector/string/deque

注意: 2是兼容1的,3是兼容2的(本质是继承关系)

 unique

void test_list3()
{list<int> lt;lt.push_back(4);lt.push_back(1);lt.push_back(1);lt.push_back(2);lt.push_back(5);lt.push_back(5);lt.push_back(3);for (auto e : lt){cout << e << " "; //4 1 1 2 5 5 3}cout << endl;lt.sort();lt.unique(); //把相邻的重复去掉, 配合sort可以达到去重的功能for (auto e : lt){cout << e << " "; //1 2 3 4 5}cout << endl;
}

splice

void test_list5()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);list<int>::iterator it = lt1.begin();++it;lt1.splice(it, lt2); //将lt2嫁接到lt1第2个位置之后, lt2就为空了!for (auto e : lt1){cout << e << " "; //1 10 20 30 40 2 3 4}cout << endl;for (auto e : lt2){cout << e << " "; //空}cout << endl;
}
void test_list5()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);lt1.splice(lt1.begin(), lt2, lt2.begin()); //将lt2的第一个节点接到lt1开始for (auto e : lt1){cout << e << " "; //10 1 2 3 4 }cout << endl;for (auto e : lt2){cout << e << " "; //20 30 40}cout << endl;
}
void test_list5()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);list<int> lt2;lt2.push_back(10);lt2.push_back(20);lt2.push_back(30);lt2.push_back(40);lt1.splice(lt1.begin(), lt2, lt2.begin(), lt2.end()); //将lt2的全部接到lt1开始for (auto e : lt1){cout << e << " "; //10 20 30 40 1 2 3 4}cout << endl;for (auto e : lt2){cout << e << " "; //空}cout << endl;
}

list模拟实现

关于带头双向链表的结构与实现可以直接看我之前的博客: 带头双向循环链表-CSDN博客

类与成员函数声明

namespace dck
{//每个节点的类型template <class T>struct list_node{T _data; //数据域list_node<T>* _next; //前驱指针list_node<T>* _prev; //后继指针list_node(const T& x = T()); //构造函数};//非const迭代器template <class T>struct __list_iterator //前加_表示内部的实现{typedef list_node<T> Node;Node* _node;//构造函数__list_iterator(Node* node);//迭代器++(前置++)typedef __list_iterator<T> self;self& operator++();//迭代器--(前置--)self& operator--();//迭代器++(后置++)self operator++(int);//迭代器--(后置--)self operator--(int);//迭代器解引用T& operator*();T* operator->();//两个迭代器进行比较bool operator!=(const self& s);bool operator ==(const self& s);};//list的类型template <class T>class list{typedef list_node<T> Node;public:void empty_init(); //空初始化list(); //构造函数void push_back(const T& x); //尾插void push_front(const T& x); //头插void pop_front(); //头删void pop_back(); //尾删iterator insert(iterator pos, const T& x); //任意位置插入iterator erase(iterator pos); //任意位置删除iterator begin(); //起始位置迭代器iterator end(); //结束位置迭代器void clear(); //清空数据~list(); //析构函数list(const list<T>& lt); //拷贝构造函数list<T>& operator=(const list<T>& lt); //赋值重载函数传统写法void swap(list<T>& lt); //交换两个list, 赋值重载函数现代写法要调用swap函数list<T>& operator=(list<T> lt); //赋值重载函数现代写法private:Node* _head;size_t size; //记录链表中节点的个数,降低时间复杂度};
}

节点类型的定义

//每个节点的类型
template <class T>
struct list_node
{T _data;list_node<T>* _next;list_node<T>* _prev;list_node(const T& x = T()) :_data(x),_next(nullptr),_prev(nullptr){}
};

非const正向迭代器的实现

之前讲解的string与vector的迭代器都是原生指针,而list的迭代器不是原生指针,主要原因是因为list的底层是双向链表,如果用原生指针++,是无法到下一个节点的;直接解引用拿到的也不是具体的数据,而是整个节点对象;而迭代器的访问与遍历方式都是类似的,都是++, 解引用,判断!=, 所以我们只需要把list的迭代器设计成类,在类中对原生指针做封装

//迭代器的实现 --- 封装屏蔽了底层差异和细节,提供了统一的访问遍历修改方式!
template <class T>
struct __list_iterator //前加_表示内部的实现
{typedef list_node<T> Node;Node* _node;//构造函数__list_iterator(Node* node):_node(node){}//迭代器++(前置++)typedef __list_iterator<T> self;self& operator++(){_node = _node->_next;return *this;}//迭代器--(前置--)self& operator--(){_node = _node->_prev;return *this;}//迭代器++(后置++)self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}//迭代器--(后置--)self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}//迭代器解引用T& operator*(){return _node->_data;}T* operator->(){return &_node->_data;}//两个迭代器进行比较bool operator!=(const self& s){return _node != s._node;}bool operator ==(const self& s){return _node == s._node;}
};

注意: 当list中存放的是自定义类型的对象时,使用->解引用时,写法如下:

class AA
{
public:AA(int aa1 = 1, int aa2 = 1):_a1(aa1),_a2(aa2){}int _a1;int _a2;
};void test_list()
{list<AA> lt1;lt1.push_back(AA(1, 2));lt1.push_back(AA(3, 4));lt1.push_back(AA(5, 6));list<AA>::iterator it = lt1.begin();while (it != lt1.end()){//显式应该这么写,因为operator->()拿到的是原生指针,还要再次->解引用拿到数据cout << it.operator->()->_a1 << " " << it.operator->()->_a2 << endl;//本来应该 it->->_a1, 但是可读性不好,因此编译器特殊处理, 省略了一个->cout << it->_a1 << " " << it->_a2 << endl;++it;}cout << endl;
}

list成员函数

构造函数
//空初始化, 后续代码可能会用到,因此单独写出来
void empty_init()
{_head = new Node;_head->_next = _head;_head->_prev = _head;_size = 0;
}//构造函数
list()
{empty_init();
}
尾插
void push_back(const T& x)
{//自己实现//Node* tail = _head->_prev; //找到尾节点//Node* newnode = new Node(x); //开辟新节点链接新节点//tail->_next = newnode;//newnode->_prev = tail;//newnode->_next = _head;//_head->_prev = newnode;//_size++;//调用insert函数insert(end(), x); 
}
头插
//头插
void push_front(const T& x)
{insert(begin(), x);
}
头删
//头删
void pop_front()
{erase(begin());
}
尾删
//尾删
void pop_back()
{erase(--end());
}
任意位置插入
//insert
//在pos位置之前插入
//list的迭代器不存在失效的问题,因为不涉及扩容
//参考库的实现,还是给insert带上返回值
iterator insert(iterator pos, const T& x)
{Node* cur = pos._node; //当前节点指针Node* prev = cur->_prev; //前一个节点指针Node* newnode = new Node(x); //开辟新节点//链接prev->_next = newnode;newnode->_prev = prev;newnode->_next = cur;cur->_prev = newnode;++_size;return iterator(newnode); //返回新插入节点位置的迭代器
}
 任意位置删除
//erase之后,迭代器pos失效,因为当前节点已经被释放了!
//因此我们给erase带上返回值
iterator erase(iterator pos)
{Node* cur = pos._node; //当前节点指针Node* prev = cur->_prev; //前一个节点指针Node* next = cur->_next; //后一个节点指针delete cur; //释放当前节点//链接前一个节点和后一个节点prev->_next = next; next->_prev = prev;--_size;return iterator(next); //返回释放节点的下一个位置
}

迭代器接口

iterator begin()
{//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化
}iterator end()
{//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化
}
清空数据
//清空数据(不清除带哨兵位的头节点)
void clear()
{iterator it = begin();while (it != end()){it = erase(it);}
}
析构函数
//析构函数
~list()
{clear();delete _head;_head = nullptr;
}
拷贝构造函数
//拷贝构造
list(list<T>& lt)
{empty_init();for (auto e : lt){push_back(e);}
}
赋值重载函数

传统写法

//赋值重载传统写法
list<T>& operator=(const list<T>& lt)
{if (this != &lt){clear(); for (auto e : lt){push_back(e);}}return *this;
}

现代写法

//赋值重载现代写法
void swap(list<T>& lt)
{std::swap(_head, lt._head);std::swap(_size, lt._size);
}list<T>& operator=(list<T> lt)
{swap(lt);return *this;
}

const迭代器的设计

上述代码实现了非const迭代器,本质就是封装了一个类,提供了对应的接口,而const迭代器本质就是迭代器指向的内容不可修改,因此不可以直接写const iterator,  这个const修饰的是迭代器本身不能被修改,那迭代器如何++访问数据呢?? 因此非const迭代器应该是一个独立的类

//非const迭代器
template <class T>
struct __list_const_iterator //前加_表示内部的实现
{typedef list_node<T> Node;Node* _node;//构造函数__list_const_iterator(Node* node):_node(node){}//迭代器++(前置++)typedef __list_const_iterator<T> self;self& operator++(){_node = _node->_next;return *this;}//迭代器--(前置--)self& operator--(){_node = _node->_prev;return *this;}//迭代器++(后置++)self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}//迭代器--(后置--)self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}//迭代器解引用const T& operator*() const{return _node->_data;}const T* operator->() const{return &_node->_data;}//两个迭代器进行比较bool operator!=(const self& s){return _node != s._node;}bool operator ==(const self& s){return _node == s._node;}
};

list类中提供const迭代器的begin和end接口即可:

//list的类型
template <class T>
class list
{typedef list_node<T> Node;
public://提供迭代器typedef __list_iterator<T> iterator;typedef __list_const_iterator<T> const_iterator;const_iterator begin() const{//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化}const_iterator end() const{//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化}
};

但是上面的写法太冗余了,非const迭代器和const迭代器都是封装了类,类中的实现大同小异,参考了STL库中的实现以后,其实只需要一个类+增加模板参数即可,  实现如下:

终极版正向迭代器的实现

//迭代器
template <class T, class Ref, class Ptr>
struct __list_iterator //前加_表示内部的实现
{typedef list_node<T> Node;Node* _node;typedef __list_iterator<T, Ref, Ptr> self;//构造函数__list_iterator(Node* node):_node(node){}//迭代器++(前置++)self& operator++(){_node = _node->_next;return *this;}//迭代器--(前置--)self& operator--(){_node = _node->_prev;return *this;}//迭代器++(后置++)self operator++(int){self tmp(*this);_node = _node->_next;return tmp;}//迭代器--(后置--)self operator--(int){self tmp(*this);_node = _node->_prev;return tmp;}//迭代器解引用Ref operator*(){return _node->_data;}Ptr operator->(){return &_node->_data;}//两个迭代器进行比较bool operator!=(const self& s){return _node != s._node;}bool operator ==(const self& s){return _node == s._node;}
};

终极版反向迭代器的实现

反向迭代器完全可以再设计一个类,在类内部把迭代器的操作都实现一遍,但是没有必要,因为我们已经有了正向迭代器,因此只需要用正向迭代器适配出反向迭代器即可, 关于容器的适配器在我的下一篇博客中有提及, 大家可以参考一下:stack 与 queue 与 priority_queue 与 仿函数 与 模板进阶-CSDN博客

反向迭代器的实现:

//用正向迭代器适配反向迭代器
template <class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;ReverseIterator(Iterator it):_it(it){}Self& operator++(){--_it;return *this;}Ref operator*(){return *_it;}Ptr operator->(){return _it.operator->();}bool operator!=(const Self& s){return _it != s._it;}private:Iterator _it;
};


list类:

template <class T>
//list的类型
class list
{typedef list_node<T> Node;
public://提供迭代器typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(--end());}reverse_iterator rend(){return reverse_iterator(end());}const_reverse_iterator rbegin() const{return const_reverse_iterator(--end());}const_reverse_iterator rend() const{return const_reverse_iterator(end());}iterator begin(){//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化}iterator end(){//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化}const_iterator begin() const{//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化}const_iterator end() const{//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化}
};

值得一说的是库中反向迭代器的实现和我们不一样,不一样的地方在于库中反向迭代器的rbegin与rend位置和我们自己写的不一样,下图rbegin和rend的位置是库中的实现,是呈现对称结构的,而库中迭代器解引用访问的是前一个数据,也就是先让原生指针--, 然后解引用访问数据! 

下面是我们模拟库中rbegin与rend的位置实现的反向迭代器:

反向迭代器的实现:

//用正向迭代器适配反向迭代器
template <class Iterator, class Ref, class Ptr>
class ReverseIterator
{
public:typedef ReverseIterator<Iterator, Ref, Ptr> Self;ReverseIterator(Iterator it):_it(it){}Self& operator++(){--_it;return *this;}Self& operator--(){++_it;return *this;}Ref operator*(){Iterator cur = _it;return *(--cur);}Ptr operator->(){return &(operator*());}bool operator!=(const Self& s){return _it != s._it;}private:Iterator _it;
};

list类:

template <class T>
//list的类型
class list
{typedef list_node<T> Node;
public://提供迭代器typedef __list_iterator<T, T&, T*> iterator;typedef __list_iterator<T, const T&, const T*> const_iterator;typedef ReverseIterator<iterator, T&, T*> reverse_iterator;typedef ReverseIterator<const_iterator, const T&, const T*> const_reverse_iterator;reverse_iterator rbegin(){return reverse_iterator(end());}reverse_iterator rend(){return reverse_iterator(begin());}const_reverse_iterator rbegin() const{return const_reverse_iterator(end());}const_reverse_iterator rend() const{return const_reverse_iterator(begin());}iterator begin(){//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化}iterator end(){//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化}const_iterator begin() const{//return iterator(_head->_next);return _head->_next;  //单参数的构造函数支持隐式类型转化}const_iterator end() const{//return iterator(_head);return _head;  //单参数的构造函数支持隐式类型转化}
};

迭代器扩充小知识

场景1:想实现一个打印函数,  无论list的节点是什么类型都能打印

template <class T>
void Print(const list<T>& lt)
{//list<T>为未实例化的类模板,编译器不能直接去他里面去找//编译器无法识别list<T>::const_iterator是内嵌类型还是静态成员变量//前面加一个typename就是告诉编译器,这里是一个类型,等list<T>实例化再去类里面去取typename list<T>::const_iterator it = lt.begin(); while (it != lt.end()){cout << *it << " ";it++;}cout << endl;
}void test_list5()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);lt1.push_back(5);Print(lt1);//list不会存在浅拷贝的问题,因为不涉及扩容list<string> lt2;lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");Print(lt2);
}

场景2:想实现一个打印函数, 无论是哪个STL,都能使用同一个打印函数

//模板(泛型编程)本质: 本来应该由我们做的事情交给编译器去做了!
template <typename Container>
void print_container(const Container& con)
{typename Container::const_iterator it = con.begin();while (it != con.end()){cout << *it << " ";it++;}cout << endl;
}void test_list5()
{list<int> lt1;lt1.push_back(1);lt1.push_back(2);lt1.push_back(3);lt1.push_back(4);lt1.push_back(5);print_container(lt1);//list不会存在浅拷贝的问题,因为不涉及扩容list<string> lt2;lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");lt2.push_back("1111111111111111");print_container(lt2);vector<string> v;v.push_back("2222222222222222");v.push_back("2222222222222222");v.push_back("2222222222222222");v.push_back("2222222222222222");v.push_back("2222222222222222");print_container(v);
}

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

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

相关文章

【c++】初阶模版与STL简单介绍

&#x1f525;个人主页&#xff1a;Quitecoder &#x1f525;专栏&#xff1a;c笔记仓 朋友们大家好&#xff0c;本篇文章介绍一下模版和对STL进行简单的介绍&#xff0c;后续我们进入对STL的学习&#xff01; 目录 模版1.泛型编程2.函数模板2.1函数模板的原理2.2模版的实例化…

03.28_111期_C++_vector特性和使用

如果写出vector这个类的时候不用缺省值&#xff0c;也不用初始化列表 那么可以编写如下构造函数&#xff0c;利用半缺省参数给没有初始化的vector实例进行赋空 但如果存在下面这两句话的设计 template <class InputIterator> vector(Inp…

前端学习<四>JavaScript基础——07-基本数据类型:Number

数值型&#xff1a;Number 在 JS 中所有的数值都是 Number 类型&#xff0c;包括整数和浮点数&#xff08;小数&#xff09;。 var a 100; // 定义一个变量 a&#xff0c;并且赋值整数100console.log(typeof a); // 输出变量 a 的类型​var b 12.3; // 定义一个变量 b&#…

大语言模型LLM《提示词工程指南》学习笔记02

文章目录 大语言模型LLM《提示词工程指南》学习笔记02设计提示时需要记住的一些技巧零样本提示少样本提示链式思考&#xff08;CoT&#xff09;提示自我一致性生成知识提示 大语言模型LLM《提示词工程指南》学习笔记02 设计提示时需要记住的一些技巧 指令 您可以使用命令来指…

【ubuntu】Vim配置记录

一、Vim介绍 vim是一个高度可定制的文本编辑器&#xff0c;有许多丰富的功能&#xff0c;扩展性极强&#xff0c;用户可以通过多种方式来增强vim vim有非常多的优点&#xff0c;例如高效率的移动&#xff0c;可以不用鼠标&#xff0c;完全用键盘操作&#xff0c;占用系统资源较…

159 Linux C++ 通讯架构实战14,epoll 函数代码实战

ngx_epoll_init函数的调用 //&#xff08;3.2&#xff09;ngx_epoll_init函数的调用&#xff08;要在子进程中执行&#xff09; //四章&#xff0c;四节 project1.cpp&#xff1a;nginx中创建worker子进程&#xff1b; //nginx中创建worker子进程 //官方nginx ,一个…

深入解析Python的lxml库:高效处理XML和HTML的利器

更多Python学习内容&#xff1a;ipengtao.com Python中的lxml库是一个强大的XML和HTML处理库&#xff0c;它基于libxml2和libxslt库&#xff0c;提供了高效的XML解析和处理功能。本文将详细介绍lxml库的安装、特性、基本功能、高级功能、实际应用场景和总结&#xff0c;帮助读者…

phpstorm设置头部注释和自定义注释内容

先说设置位置&#xff1a; PhpStorm中文件、类、函数等注释的设置在&#xff1a;setting-》Editor-》FIle and Code Template-》Includes-》PHP Function Doc Comment下设置即可&#xff0c;其中方法的默认是这样的&#xff1a; /** ${PARAM_DOC} #if (${TYPE_HINT} ! "…

Unity与CocosCraetor对比学习三

一、计时器 1.在Creator中 void start() {// js中的计时器// 延迟1秒后执行一次&#xff0c;不受Cocos限制setTimeout(() > {console.log("haha");}, 1000);// 每隔1秒执行一次setInterval(() > {console.log("haha");}, 1000);// creator中的计时…

计算机网络的分层结构及模型

1.计算机网络分层的基本原则 &#xff08;1&#xff09;各层之间相互独立&#xff0c;每层只实现一种相对独立的功能 &#xff08;2&#xff09;每层之间的交互尽可能少 &#xff08;3&#xff09;结构上可分割开&#xff0c;每层都采用最合适的技术来实现 &#xff08;4&…

Linux第4课 Linux的基本操作

文章目录 Linux第4课 Linux的基本操作一、图形界面介绍二、终端界面介绍 Linux第4课 Linux的基本操作 一、图形界面介绍 本节以Ubuntu系统的GUI为例进行说明&#xff0c;Linux其他版本可自行网搜。 图形系统进入后&#xff0c;左侧黄框内为菜单栏&#xff0c;右侧为桌面&…

在订单流程中锁定库存的最佳时机

目录 1. 用户点击结算时锁定库存 2. 用户提交订单时锁定库存 3. 用户支付成功后锁定库存 最佳时机选择 1. 用户点击结算时锁定库存 优点&#xff1a;确保用户在决定购买时商品是可用的&#xff0c;增加了用户的购买信心。缺点&#xff1a;如果用户在结算后放弃购买&#x…

嵌入式开发中内存管理与优化

内存管理与优化 在嵌入式开发中&#xff0c;内存管理是一项至关重要的任务&#xff0c;直接影响到系统的稳定性和性能。由于嵌入式设备通常资源有限&#xff0c;尤其是内存资源&#xff0c;因此内存管理与优化显得尤为重要。 具体实现 1. 静态内存分配 静态内存分配是指在编…

[HackMyVM]靶场Birthday

难度:Hard kali:192.168.56.104 靶机:192.168.56.149 端口扫描 ┌──(root㉿kali2)-[~/Desktop] └─# nmap 192.168.56.149 Starting Nmap 7.94SVN ( https://nmap.org ) at 2024-04-06 10:39 CST Nmap scan report for 192.168.56.149 Host is up (0.00016s latency). N…

硬件-1、体系架构

cpu 处理器 arm处理器的七种工作模式 arm寄存器 两张图是一样的&#xff0c;r0---r12是通用寄存器。其他寄存器可参考图一&#xff0c;cpu架构。 程序状态寄存器psr&#xff08;cpsr/spsr&#xff09; 程序异常处理 理解示例 当使用swi&#xff08;软中断指令&#xff09;指令…

【VMware Workstation】启动虚拟机报错“此主机支持 AMD-V,但 AMD-V 处于禁用状态”

问题出现步骤&#xff1a; 打开虚拟机&#xff1a; 然后报错&#xff1a; “此主机支持 AMD-V&#xff0c;但 AMD-V 处于禁用状态。 如果已在 BIOS/固件设置中禁用 AMD-V&#xff0c;或主机自更改此设置后从未重新启动&#xff0c;则 AMD-V 可能被禁用。 (1) 确认 BIOS/固件设…

机器学习KNN最邻近分类算法

文章目录 1、KNN算法简介2、KNN算法实现2.1、调用scikit-learn库中KNN算法 3、使用scikit-learn库生成数据集3.1、自定义函数划分数据集3.2、使用scikit-learn库划分数据集 4、使用scikit-learn库对鸢尾花数据集进行分类5、什么是超参数5.1、实现寻找超参数5.2、使用scikit-lea…

数据分析 -- numpy

文章目录 numpy库简介简介特点 numpy操作数组创建数组属性数组变更数据计算 numpy库简介 简介 开源的Python库&#xff0c;它提供了高性能的多维数值&#xff08;numpy.ndarray&#xff09;计算能力&#xff1b;由“Numerical Python”缩写而来&#xff0c;并且它是Pandas库的…

Zabbix6 - Centos7部署Grafana可视化图形监控系统配置手册手册

Zabbix6 - Centos7部署Grafana可视化图形监控系统配置手册手册 概述&#xff1a; Grafana是一个开源的数据可视化和监控平台。其特点&#xff1a; 1&#xff09;丰富的可视化显示插件&#xff0c;包括热图、折线图、饼图&#xff0c;表格等&#xff1b; 2&#xff09;支持多数据…

L2-2 口罩发放 (25 分)

坑点&#xff1a; 应该就是题目要求的身份证号唯一 然后是相同的人同一天多次申请 然后是时间相同按照申请记录排序 需要注意的是&#xff0c;不要在同一天内看到满足要求的就直接发放口罩&#xff0c;有可能发完之后发现后面的人的时间更早 #include "bits/stdc.h" …