c++ - list常用接口模拟实现

news2025/3/16 13:38:56

文章目录

    • 一、模拟list类的框架
    • 二、函数接口实现
      • 1、迭代器接口
      • 2、常用删除、插入接口
      • 3、常用其他的一些函数接口
      • 4、默认成员函数


一、模拟list类的框架

1、使用带哨兵的双向链表实现。
2、链表结点:

// List的结点类
template<class T>
struct ListNode
{
    ListNode<T>* _pPre; //后继指针
    ListNode<T>* _pNext; //前驱指针
    T _val; //数据
    //构造结点
    ListNode(const T& val = T()) :_val(val), _pPre(nullptr), _pNext(nullptr)
    {}
};

3、list类的成员变量和构造双向链表的哨兵位结点函数。

 //让哨兵位结点指向自己
typedef ListNode<T> Node;
typedef Node* PNode;

void CreateHead()
 {
     _pHead = new  Node;
     _pHead->_pNext = _pHead;
     _pHead->_pPre = _pHead;
 }
 
 PNode _pHead;   //哨兵位结点

二、函数接口实现

1、迭代器接口

list的迭代器是双向迭代器,支持++、–,但是它们在内存上储存是不连续的,无法简单通过指针去进行++、–操作,所以我们要对list的迭代器进行封装。
(1)list正向迭代器类
成员变量:两个结点指针。

typedef ListNode<T>* PNode;
PNode _pNode;	//结点指针
PNode _P;//保存哨兵位结点指针,用于判断解引用是否访问哨兵位结点

构造函数:

//构造函数 ,获取一个结点指针
  ListIterator(const PNode & pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode),_P(P)
    {}

拷贝构造、赋值、析构函数:
因为_pNode的指针指向的内存是有list类释放的,所以该类无需进行资源清理,使用浅拷贝即可,所以拷贝、赋值、析构都使用编译器生成的即可。

重载操作符:

	//Ref为T& Ptr为T*
   typedef ListIterator<T, Ref, Ptr> Self;
   	//解引用
    Ref operator*()
    {
          assert(_P != _pNode);

        return _pNode->_val;
    }
    //该运算符重载的意义为T为自定义类型时使用,迭代器可以通过该运算符直接访问自定义类型成员
    Ptr operator->()
    {
        return &(_pNode->_val);
    }
    //前置++
    Self& operator++()
    {
        _pNode = _pNode->_pNext;
        return *this;
    }
    //后置++
    Self operator++(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pNext;
        return tmp;
    }
    //前置--
    Self& operator--()
    {
        _pNode = _pNode->_pPre;
        return *this;
    }
    //后置--
    Self& operator--(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pPre;
        return tmp;
    }
    //比较
    bool operator!=(const Self& l)
    {
        return l._pNode != _pNode;
    }
    bool operator==(const Self& l)
    {
        return l._pNode == _pNode;
    }

获取成员变量函数:

 //获取该迭代器成员变量
    PNode get()
    {
        return _pNode;
    }

ListIterator类一览:

//Ref为T& Ptr为T*
template<class T, class Ref, class Ptr>
class ListIterator
{
    typedef ListNode<T>* PNode;
    typedef ListIterator<T, Ref, Ptr> Self;
public:
    //构造函数 ,获取一个结点指针
    ListIterator(const PNode & pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode),_P(P)
    {}
    Ref operator*()
    {
        assert(_P != _pNode);

        return _pNode->_val;
    }
    Ptr operator->()
    {
        return &(operator*());
    }
    Self& operator++()
    {
        _pNode = _pNode->_pNext;
        return *this;
    }
    Self operator++(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pNext;
        return tmp;
    }
    Self& operator--()
    {
        _pNode = _pNode->_pPre;
        return *this;
    }
    Self& operator--(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pPre;
        return tmp;
    }
    bool operator!=(const Self& l)
    {
        return l._pNode != _pNode;
    }
    bool operator==(const Self& l)
    {
        return l._pNode == _pNode;
    }
    PNode get()
    {
        return _pNode;
    }
private:
    PNode _pNode;
    PNode _P;
};
};

(2)反向迭代器类
与正向迭代器不一样的有 * 操作符,_pNode保存的是有效元素的下一个位置,如:想要的是_pNode->_pPre指向的元素,但是该迭代器保存的是_pNode的指针,还有++,–与正向迭代器相反。
其他操作与正向迭代器一致。

template<class T, class Ref, class Ptr>
class Reverse_ListIterator
{
    typedef ListNode<T>* PNode;
    typedef Reverse_ListIterator<T, Ref, Ptr> Self;
public:
    Reverse_ListIterator(const PNode& pNode = nullptr, const PNode& const P = nullptr) :_pNode(pNode), _P(P)
    {}
    Ref operator*()
    {
        assert(_P != _pNode ->_pPre);
        return _pNode->_pPre->_val;
    }
    Ptr operator->()
    {
        return &(operator*());
    }
    Self& operator++()
    {
        _pNode = _pNode->_pPre;
        return *this;
    }
    Self operator++(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pPre;
        return tmp;
    }
    Self& operator--()
    {
        _pNode = _pNode->_pNext;
    }
    Self& operator--(int)
    {
        Self tmp(_pNode);
        _pNode = _pNode->_pNext;
        return tmp;
    }
    bool operator!=(const Self& l)
    {
        return l._pNode != _pNode;
    }
    bool operator==(const Self& l)
    {
        return l._pNode == _pNode;
    }
    PNode get()
    {
        return _pNode;
    }
private:
    PNode _pNode;
    PNode _P;
};
    

(3)list迭代器接口

//一些类型的重命名
 typedef ListIterator<T, T&, T*> iterator;
 typedef ListIterator<T, const T&, const T*> const_iterator;
 typedef Reverse_ListIterator<T, T&, T*> reverse_iterator;
 typedef Reverse_ListIterator<T, const T&, const T*> reverse_const_iterator;

// List Iterator

//第一个有效元素位置的迭代器
iterator begin()
{
    return iterator(_pHead->_pNext,_pHead);
}
//最后一个有效元素位置的下一个位置的迭代器
iterator end()
{
    return iterator(_pHead,_pHead);
}
//加了const 修饰
const_iterator begin() const
{
    return const_iterator(_pHead->_pNext,_pHead);
}
const_iterator end()const
{
    return const_iterator(_pHead,_pHead);
}

//反向迭代器
//哨兵位的位置
  reverse_iterator rbegin()
  {
      return reverse_iterator(_pHead,_pHead);
  }
//第一个有效元素位置
  reverse_iterator rend()
  {
      return reverse_iterator(_pHead ->_pNext,_pHead);
  }
//加了const修饰
  reverse_const_iterator rbegin() const
  {
      return reverse_const_iterator(_pHead,_pHead);
  }
  reverse_const_iterator rend()const
  {
      return reverse_const_iterator(_pHead->_pNext,_pHead);
  }

2、常用删除、插入接口

(1)insert
在迭代器位置前插入一个结点。

// 在pos位置前插入值为val的节点
iterator insert(iterator pos, const T & val)
{
    //创造一个结点
    PNode tmp = new Node(val);

    //获取迭代器中的指针
    PNode _pos = pos.get();

    //进行插入
    PNode prv = _pos->_pPre;
    prv->_pNext = tmp;
    tmp->_pPre = prv;
    tmp->_pNext = _pos;
    _pos->_pPre = tmp;

    //返回新迭代器
    return iterator(tmp);
}

迭代器是否失效:
因为插入新的结点,不会影响到原来的结点,所以该迭代器不会失效。

(2)erase
删除迭代器位置结点。

// 删除pos位置的节点,返回该节点的下一个位置
iterator erase(iterator pos)
{
    //判断是否为哨兵位结点
    iterator it = end();
    assert(pos != it);

    //获取迭代器结点指针
    PNode tmp = pos.get();

    //进行删除
    PNode next = tmp->_pNext;
    PNode prv = tmp->_pPre;
    prv->_pNext = next;
    next->_pPre = prv;
    delete tmp;
    tmp = nullptr;

    //返回被删除结点的下一个位置的结点迭代器
    return iterator(next);
}

迭代器是否失效:
因为将结点删除了,所以原本的迭代器是不能使用的,所以迭代器失效了。

(3)push_back、pop_back、push_front、pop_front
这里的头插、尾插、头删、尾删均复用上面两个函数接口。

void 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()); }

3、常用其他的一些函数接口

(1)size
返回大小,通过遍历链表即可找到。

size_t size()const
{
	//保存哨兵位的下一个位置
    PNode tmp = _pHead->_pNext;
	
	//开始遍历
    size_t count = 0;
    while (tmp != _pHead)
    {
        tmp = tmp->_pNext;
        ++count;
    }
    
    return count;
}

(2)empty
是否为空,判断哨兵位结点是否指向自己即可。

bool empty()const
{
    return _pHead == _pHead->_pNext;
}

(3)clear
清空链表,遍历链表逐个清空,保留哨兵位结点,再让哨兵位结点自己连接自己。

  void clear()
  {
      //保存有效结点位置
      PNode tmp = _pHead->_pNext;

      //遍历删除
      while (tmp != _pHead)
      {
          PNode p = tmp->_pNext;
          delete tmp;
          tmp = p;
      }
      //重新指向
      _pHead->_pNext = _pHead;
      _pHead->_pPre = _pHead;
           

(4)swap
交换,只需要交换指向哨兵位结点的指针即可。
在这里插入图片描述

void swap(list<T>& l)
{
    std::swap(_pHead, l._pHead);         
}

(4)front
获取第一个位置的元素。

T& front()
{
    assert(!empty());
    return _pHead->_pNext->_val;
}
const T& front()const
{
    assert(!empty());
    return _pHead->_pNext->_val;
}

(5)back
获取最后一个位置元素。

T& back()
{
    assert(!empty());
    return _pHead->_pPre->_val;
}
const T& back()const
{
    assert(!empty());
    return _pHead->_pPre->_val;
}

4、默认成员函数

(1)构造函数
构造函数都会先进行构造哨兵位结点,再进行下面的操作,除了无参构造,其他都复用了尾插,将元素尾插到链表结尾。

//无参构造
list() 
{   //构造一个哨兵位结点
    CreateHead(); 
}

//利用n个val值进行构造
list(int n, const T& value = T())
{
    //构造一个哨兵位结点
    CreateHead();

    //将元素尾插入
    while (n != 0)
    {
        push_back(value);
        --n;
    }
}

//这里用迭代器区间构造,重写一个模板,使其可以使用其他容器的迭代器
template <class Iterator>
list(Iterator first, Iterator last)
{
    //构造一个哨兵位结点
    CreateHead();
    //将元素尾插入
    while (first != last)
    {
        push_back(*first);
        ++first;
    }
}

//拷贝构造
list(const list<T>& l)
{
    //构造一个哨兵位结点
    CreateHead();

    //遍历+将元素尾插入
    PNode tmp = l._pHead->_pNext;
    while (tmp != l._pHead)
    {
        push_back(tmp->_val);
        tmp = tmp->_pNext;
    }
}

(2)重载赋值运算符
通过传值传参构造一个临时容器 l ,再将其与原来的容器交换,当出了函数作用域之后临时容器就会调用析构函数,对临时容器的资源进行清理(就是原来容器的资源)。

list<T>& operator=(list<T> l)
{
    //与临时变量进行交换
    swap(l);
    return *this;
}

(3)析构函数
对链表清理。

~list()
{
    //清空链表
    clear();
    //删除哨兵位结点
    delete _pHead;
    _pHead = nullptr;
}

三、总代码

#pragma once
#include<iostream>
#include<assert.h>
#include<string>
using namespace std;

namespace xu
{
    // List的结点类
    template<class T>
    struct ListNode
    {
        ListNode<T>* _pPre; //后继指针
        ListNode<T>* _pNext; //前驱指针
        T _val; //数据
        //构造结点
        ListNode(const T& val = T()) :_val(val), _pPre(nullptr), _pNext(nullptr)
        {}
    };


    //List的正向迭代器类
    //Ref为T& Ptr为T*
    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)
        {}
        Ref operator*()
        {
            return _pNode->_val;
        }
        Ptr operator->()
        {
            return &(operator*());
        }
        Self& operator++()
        {
            _pNode = _pNode->_pNext;
            return *this;
        }
        Self operator++(int)
        {
            Self tmp(_pNode);
            _pNode = _pNode->_pNext;
            return tmp;
        }
        Self& operator--()
        {
            _pNode = _pNode->_pPre;
            return *this;
        }
        Self& operator--(int)
        {
            Self tmp(_pNode);
            _pNode = _pNode->_pPre;
            return tmp;
        }
        bool operator!=(const Self& l)
        {
            return l._pNode != _pNode;
        }
        bool operator==(const Self& l)
        {
            return l._pNode == _pNode;
        }
        PNode get()
        {
            return _pNode;
        }
    private:
        PNode _pNode;
    };

    //List的反向迭代器类
    template<class T, class Ref, class Ptr>
    class Reverse_ListIterator
    {
        typedef ListNode<T>* PNode;
        typedef Reverse_ListIterator<T, Ref, Ptr> Self;
    public:
        Reverse_ListIterator(PNode pNode = nullptr) :_pNode(pNode)
        {}
        Ref operator*()
        {
            return _pNode->_pPre->_val;
        }
        Ptr operator->()
        {
            return &(operator*());
        }
        Self& operator++()
        {
            _pNode = _pNode->_pPre;
            return *this;
        }
        Self operator++(int)
        {
            Self tmp(_pNode);
            _pNode = _pNode->_pPre;
            return tmp;
        }
        Self& operator--()
        {
            _pNode = _pNode->_pNext;
        }
        Self& operator--(int)
        {
            Self tmp(_pNode);
            _pNode = _pNode->_pNext;
            return tmp;
        }
        bool operator!=(const Self& l)
        {
            return l._pNode != _pNode;
        }
        bool operator==(const Self& l)
        {
            return l._pNode == _pNode;
        }
        PNode get()
        {
            return _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;
        typedef Reverse_ListIterator<T, T&, T*> reverse_iterator;
        typedef Reverse_ListIterator<T, const T&, const T*> reverse_const_iterator;
    public:
        //默认构造

        list() 
        {   //构造一个哨兵位结点
            CreateHead(); 
        }
        list(int n, const T& value = T())
        {
            //构造一个哨兵位结点
            CreateHead();

            //将元素尾插入
            while (n != 0)
            {
                push_back(value);
                --n;
            }
        }
        template <class Iterator>
        list(Iterator first, Iterator last)
        {
            //构造一个哨兵位结点
            CreateHead();
            //将元素尾插入
            while (first != last)
            {
                push_back(*first);
                ++first;
            }
        }
        list(const list<T>& l)
        {
            //构造一个哨兵位结点
            CreateHead();

            //遍历+将元素尾插入
            PNode tmp = l._pHead->_pNext;
            while (tmp != l._pHead)
            {
                push_back(tmp->_val);
                tmp = tmp->_pNext;
            }
        }

        list<T>& operator=(list<T> l)
        {
            //与临时变量进行交换
            swap(l);
            return *this;
        }

        ~list()
        {
            //清空链表
            clear();
            //删除哨兵位结点
            delete _pHead;
            _pHead = nullptr;
        }

        ///
        // List Iterator
        iterator 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);
        }

        reverse_iterator rbegin()
        {
            return reverse_iterator(_pHead);
        }
        reverse_iterator rend()
        {
            return reverse_iterator(_pHead ->_pNext);
        }

        reverse_const_iterator rbegin() const
        {
            return reverse_const_iterator(_pHead);
        }
        reverse_const_iterator rend()const
        {
            return reverse_const_iterator(_pHead->_pNext);
        }


            ///
            // List Capacity
            size_t size()const
            {
                PNode tmp = _pHead->_pNext;

                size_t count = 0;
                while (tmp != _pHead)
                {
                    tmp = tmp->_pNext;
                    ++count;
                }
                return count;
            }
            bool empty()const
            {
                return _pHead == _pHead->_pNext;
            }


            
            // List Access
            T& front()
            {
                assert(!empty());
                return _pHead->_pNext->_val;
            }
            const T& front()const
            {
                assert(!empty());
                return _pHead->_pNext->_val;
            }
            T& back()
            {
                assert(!empty());
                return _pHead->_pPre->_val;
            }
            const T& back()const
            {
                assert(!empty());
                return _pHead->_pPre->_val;
            }


            
            // List Modify
            void 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()); }

            // 在pos位置前插入值为val的节点
            iterator insert(iterator pos, const T & val)
            {
                //创造一个结点
                PNode tmp = new Node(val);

                //获取迭代器中的指针
                PNode _pos = pos.get();

                //进行插入
                PNode prv = _pos->_pPre;
                prv->_pNext = tmp;
                tmp->_pPre = prv;
                tmp->_pNext = _pos;
                _pos->_pPre = tmp;

                //返回新迭代器
                return iterator(tmp);
            }
            // 删除pos位置的节点,返回该节点的下一个位置
            iterator erase(iterator pos)
            {
                //判断是否为哨兵位结点
                iterator it = end();
                assert(pos != it);

                //获取迭代器结点指针
                PNode tmp = pos.get();

                //进行删除
                PNode next = tmp->_pNext;
                PNode prv = tmp->_pPre;
                prv->_pNext = next;
                next->_pPre = prv;
                delete tmp;
                tmp = nullptr;

                //返回被删除结点的下一个位置的结点迭代器
                return iterator(next);
            }
          
            void clear()
            {
                //保存有效结点位置
                PNode tmp = _pHead->_pNext;

                //遍历删除
                while (tmp != _pHead)
                {
                    PNode p = tmp->_pNext;
                    delete tmp;
                    tmp = p;
                }
                //重新指向
                _pHead->_pNext = _pHead;
                _pHead->_pPre = _pHead;
            }

            void swap(list<T>& l)
            {
                std::swap(_pHead, l._pHead);
            }

        private:
            //让哨兵位结点指向自己
            void CreateHead()
            {
                _pHead = new  Node;
                _pHead->_pNext = _pHead;
                _pHead->_pPre = _pHead;
            }
            PNode _pHead;   //哨兵位结点
        };
    };

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

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

相关文章

中央财政支持农业投资重点领域指引,涉及7大领域

中央财政支持农业投资重点领域指引 紧扣推进农业现代化走在前重大任务&#xff0c;根据农业农村部《社会资本投资农业农村指引》&#xff0c;结合实际&#xff0c;鼓励支持国内外社会资本、各类市场主体在境内重点投资稳产保供、科技创新、设施农业、智慧农业、绿色农业和产业…

systemctlm-cosim-demo项目分析

概述 systemctlm-cosim-demo项目是Xilinx的systemc库的demo工程。 环境安装 qemu安装 cd xilinx_proj/Downloads git clone https://github.com/Xilinx/qemu.git cd qemu git checkout 74d70f8008# Configure and build # zynq7000 # ./configure --target-list"arm-s…

3DMAX一键虚线图形插件DashedShape使用方法

3DMAX一键虚线图形插件使用方法 3dMax一键虚线图形插件&#xff0c;允许从场景中拾取的样条线创建虚线形状。该工具使你能够创建完全自定义的填充图案&#xff0c;为线段设置不同的材质ID&#xff0c;并在视口中进行方便的预览。 【版本要求】 3dMax 2012 – 2025&#xff08;…

太强了!斯坦福大学吴恩达教授机器学习深度学习速查表

吴恩达教授在2012年推出的『机器学习』课程已经收获了超过 480 万学习者。2022年课程团队对其进行更新升级&#xff0c;广泛地介绍了现代机器学习&#xff0c;以及硅谷用于人工智能和机器学习创新的一些最佳实践&#xff08;评估和调整模型&#xff0c;采用以数据为中心的方法来…

SpringBoot社区配送服务系统小程序-计算机毕业设计源码88705

摘要 随着科学技术的飞速发展&#xff0c;社会的方方面面、各行各业都在努力与现代的先进技术接轨&#xff0c;通过科技手段来提高自身的优势&#xff0c;社区当然也不例外。社区配送服务系统小程序是以实际运用为开发背景&#xff0c;运用软件工程原理和开发方法&#xff0c;采…

c++ - 模板(二)

文章目录 一、模板参数缺省值二、非类型模板参数三、模板的特化四、模板的分离编译 一、模板参数缺省值 给模板初始值与给函数初始值类似&#xff0c;当需要给一部分缺省值时&#xff0c;参数缺省值必须从右向左给&#xff0c;中间不能留着参数不给缺省值。 template< cla…

yangwebrtc x86_64环境搭建

版本&#xff1a;5.0.099 sudo apt-get install libxext-dev sudo apt-get install x11proto-xext-dev sudo apt-get install libxi-dev sudo apt install libasound2-dev sudo apt install libgl1-mesa-dev sudo apt-get install libxtst-dev 用qt打开以下两个项目的.pro met…

主机加固的最后一米防护

智慧互联的浪潮正席卷全球&#xff0c;它不仅重塑了传统的工业格局&#xff0c;也催生了无数创新的商业模式。随着物联网和互联网技术的飞速发展&#xff0c;智能化、自动化、联网化已成为未来各个行业的发展方向。然而&#xff0c;智慧物联的开放性、系统的漏洞以及基于用户、…

前端开发入门指南:掌握网页设计的第一课

UI设计与前端开发是相辅相成&#xff0c;UI设计可以视觉美化产品界面&#xff0c;而前端开发可以通过代码实现设计稿。作为UI设计师&#xff0c;如果画出来的图片美观方便对前端开发者非常有益。如果设计复比较难以实现&#xff0c;沟通就会变得更加困难。因此&#xff0c;UI设…

从高海拔到严寒季的测量作业更要「快准稳」,怎么实现?

西藏那曲海拔4500米公路勘测项目赶工期 “必须要保障在西藏那曲地区承接的公路勘测项目赶工期需求&#xff0c;海拔高达4500米、网络通讯不足、部分范围存在无网以及地基信号覆盖可能不足的情况&#xff0c;需要能满足环境和项目需求的专业RTK设备紧急送到。” 客户的一个电话…

保护关键业务资产的四个步骤

提到 “关键资产 ”&#xff0c;相信大家并不陌生&#xff0c;它是企业 IT 基础设施中对组织运作至关重要的技术资产。如果这些资产&#xff08;如应用服务器、数据库或特权身份&#xff09;出现问题&#xff0c;势必会对企业安全态势造成严重影响。 但每项技术资产都被视为关…

【K8s】专题四(5):Kubernetes 控制器之 DaemonSet

以下内容均来自个人笔记并重新梳理&#xff0c;如有错误欢迎指正&#xff01;如果对您有帮助&#xff0c;烦请点赞、关注、转发&#xff01;欢迎扫码关注个人公众号&#xff01; 目录 一、基本介绍 二、工作原理 三、相关特性 四、资源清单&#xff08;示例&#xff09; 五…

[数据集][目标检测]叶子计数检测数据集VOC+YOLO格式240张1类别

数据集格式&#xff1a;Pascal VOC格式YOLO格式(不包含分割路径的txt文件&#xff0c;仅仅包含jpg图片以及对应的VOC格式xml文件和yolo格式txt文件) 图片数量(jpg文件个数)&#xff1a;240 标注数量(xml文件个数)&#xff1a;240 标注数量(txt文件个数)&#xff1a;240 标注类别…

银河麒麟操作系统通过首批软件供应链安全能力认证

麒麟软件产品供应链安全能力获双重肯定&#xff01;5月30日&#xff0c;经北京赛迪认证中心评估&#xff0c;银河麒麟高级服务器操作系统V10和银河麒麟桌面操作系统V10成为首批获得软件供应链安全能力认证产品&#xff0c;并在操作系统类产品中名列前茅。 软件供应链安全能力评…

2024年数字化经济与智慧金融国际会议(ICDESF 2024)

2024 International Conference on Digital Economy and Smart Finance 【1】大会信息 大会时间&#xff1a;2024-07-22 大会地点&#xff1a;中国成都 截稿时间&#xff1a;2024-07-10(以官网为准&#xff09; 审稿通知&#xff1a;投稿后2-3日内通知 会议官网&#xff1a;h…

Leetcode 力扣108. 代码测试用例测试结果测试结果108. 将有序数组转换为二叉搜索树 (抖音号:708231408)

给你一个整数数组 nums &#xff0c;其中元素已经按 升序 排列&#xff0c;请你将其转换为一棵 平衡 二叉搜索树。 示例 1&#xff1a; 输入&#xff1a;nums [-10,-3,0,5,9] 输出&#xff1a;[0,-3,9,-10,null,5] 解释&#xff1a;[0,-10,5,null,-3,null,9] 也将被视为正确…

mysql用户管理知识点

1、权限表 1.1、user表 1.1.1、用户列 Host、User、Password分别表示主机名、用户名、密码 1.1.2、权限列 决定了用户的权限&#xff0c;描述了在全局范围内允许对数据和数据库进行操作。 1.1.3、安全列 安全列有6个字段&#xff0c;其中两个是ssl相关的&#xff0c;2个是x509相…

使用API有效率地管理Dynadot域名,创建文件夹管理域名

关于Dynadot Dynadot是通过ICANN认证的域名注册商&#xff0c;自2002年成立以来&#xff0c;服务于全球108个国家和地区的客户&#xff0c;为数以万计的客户提供简洁&#xff0c;优惠&#xff0c;安全的域名注册以及管理服务。 Dynadot平台操作教程索引&#xff08;包括域名邮…

mobaxterm怎么ssh连接

要使用 MobaXterm 进行 SSH 连接&#xff0c;请按照以下步骤操作&#xff1a; 1、首先&#xff0c;确保已经安装了 MobaXterm 软件。 你可以在官方网站&#xff08;https://mobaxterm.mobatek.net/&#xff09;上下载并安装它。 2、打开 MobaXterm 软件后&#xff0c;你会看…

新手快速上手IDEA【常用快捷键】

目录 一、常用二、进阶&#xff08;提高编码速度&#xff09;三、其他四、查找、替换与关闭最后 一、常用 说明快捷键复制代码ctrl c粘贴ctrl v剪切ctrl x撤销ctrl z反撤销ctrl shift z保存-save allctrl s全选-select allctrl a 二、进阶&#xff08;提高编码速度&a…