C++:List的使用和模擬實現

???學習的道路很枯燥,希望我們能并肩走下來!

文章目錄

目錄

文章目錄

前言

一 list的介紹及使用

1.1 list的介紹

1.2 list的使用?

1.2.1?list的構造

1.2.2 list iterator的使用

1.2.3 list capacity?

1.2.4 list element access?

?1.2.5 list modifiers

1.2.6 list的迭代器失效?

?1.2.7?List中sort的效率測試

二、list的模擬實現

?2.1 正向迭代器的實現

2.1.1 正向迭代器的封裝?

?2.1.2 迭代器的使用

2.2?list相關的成員函數

?2.2.1?構造函數

2.2.1.1 默認構造函數

?2.2.1.2 有參構造函數

?2.2.1.3 迭代器區間構造函數?

2.2.1.4 拷貝構造?

1.傳統?

2.現代?

2.2.2 析構函數和clear

2.2.2.1 析構函數

2.2.2.2 clear()

?2.2.3 賦值重載

2.2.4.1?empty、size

?2.2.4.2 insert

2.2.4.3 erase?

2.2.4.4 尾插尾刪頭插頭刪?

2.3 反向迭代器的實現?

?

三 list模擬實現的全部代碼


前言

本篇詳細介紹了list的使用和模擬實現,讓使用者了解list,而不是僅僅停留在表面,更好的模擬,為了更好的使用. 文章可能出現錯誤,如有請在評論區指正,讓我們一起交流,共同進步!


一 list的介紹及使用

1.1 list的介紹

list文本介紹

1. list是可以在常數范圍內在任意位置進行插入和刪除的序列式容器,并且該容器可以前后雙向迭代

2. list的底層是雙向鏈表結構,雙向鏈表中每個元素存儲在互不相關的獨立節點中,在節點中通過指針指向其前一個元素和后一個元素。

3. list與forward_list非常相似:最主要的不同在于forward_list是單鏈表,只能朝前迭代,已讓其更簡單高效。

4. 與其他的序列式容器相比(array,vector,deque),list通常在任意位置進行插入、移除元素的執行效率更好。

5. 與其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的隨機訪問,比如:要訪問list 的第6個元素,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時間開銷;list還需要一些額外的空間,以保存每個節點的相關聯信息(對于存儲類型較小元素的大list來說這可能是一個重要的因素)

1.2 list的使用?

list中的接口比較多,此處類似,只需要掌握如何正確的使用,然后再去深入研究背后的原理,已達到可擴展 的能力。以下為list中一些常見的重要接口。

1.2.1?list的構造

構造函數( (constructor))接口說明
list (size_type n, const value_type& val = value_type())構造的list中包含n個值為val的元素
list()構造空的list
list (const list& x)拷貝構造函數
list (InputIterator first, InputIterator last)用[first, last)區間中的元素構造list

1.2.2 list iterator的使用

此處,大家可暫時將迭代器理解成一個指針,該指針指向list中的某個節點

函數聲明接口說明
begin + end返回第一個元素的迭代器+返回最后一個元素下一個位置的迭代器
rbegin + rend返回第一個元素的reverse_iterator,即end位置,返回最后一個元素下一個位置的 reverse_iterator,即begin位置

【注意】

1. begin與end為正向迭代器,對迭代器執行++操作,迭代器向后移動

2. rbegin(end)與rend(begin)為反向迭代器,對迭代器執行++操作,迭代器向前移動?

1.2.3 list capacity?

函數聲明接口說明
empty檢測list是否為空,是返回true,否則返回false
size返回list中有效節點的個數

1.2.4 list element access?

函數聲明接口說明
front返回list的第一個節點中值的引用
back返回list的最后一個節點中值的引用

?1.2.5 list modifiers

函數聲明接口說明
push_front在list首元素前插入值為val的元素
pop_front刪除list中第一個元素
push_back在list尾部插入值為val的元素
pop_back刪除list中最后一個元素
insert在list position 位置中插入值為val的元素
erase刪除list position位置的元素
swap交換兩個list中的元素
clear清空list中的有效元素

list中還有一些操作,需要用到時大家可參閱list的文檔說明。

1.2.6 list的迭代器失效?

前面說過,此處大家可將迭代器暫時理解成類似于指針

迭代器失效即迭代器所指向的節點的無效,即該節點被刪除了。

因為list的底層結構為帶頭結點的雙向循環鏈表,因此在list中進行插入時是不會導致list的迭代器失效的,只有在刪除時才會失效,并且失效的只是指向被刪除節點的迭代器,其他迭代器不會受到影響。

void TestListIterator1(){int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array+sizeof(array)/sizeof(array[0]));auto it = l.begin();while (it != l.end()){// erase()函數執行后,it所指向的節點已被刪除,因此it無效,在下一次使用it時,必須先給
其賦值l.erase(it);  ++it;}}// 改正
void TestListIterator(){int array[] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 0 };list<int> l(array, array+sizeof(array)/sizeof(array[0]));auto it = l.begin();while (it != l.end()){l.erase(it++);    }}

?1.2.7?List中sort的效率測試

我們用一段代碼來測試一下list中sort的性能

#include<iostream>
#include<algorithm>
#include<vector>
#include<list>
using namespace std;
void test_op()
{srand((unsigned int)time(NULL));const int N = 1000000;vector<int> v;v.reserve(N);list<int> lt1;list<int> lt2;for (int i = 0; i < N; ++i){int e = rand();lt1.push_back(e);lt2.push_back(e);}// 拷貝到vector排序,排完以后再拷貝回來int begin1 = clock();for (auto e : lt1){v.push_back(e);}sort(v.begin(), v.end());size_t i = 0;for (auto& e : lt1){e = v[i++];}int end1 = clock();//list調用自己的sortint begin2 = clock();lt2.sort();int end2 = clock();printf("vector sort:%d\n", end1 - begin1);printf("list sort:%d\n", end2 - begin2);
}

?

會發現哪怕我先拷貝到vector排完再拷貝回去效率都比list的sort效率高,所以list的sort實際中意義不是很大!!?

二、list的模擬實現

?2.1 正向迭代器的實現

2.1.1 正向迭代器的封裝?

我們在學習vector的時候,發現vector的迭代器就是一個原生指針T*,這得益于vector的空間的連續性

那我們還能像vector一樣用原生指針去修飾迭代器嗎?

不能,鏈表空間上是不連續的,那我們對一個節點指針進行加減,就很難說能不能找到下一個節點,更多的是找不到的情況

我們在數據結構中訪問下一個節點,往往是利用當前節點存的下一節點的地址來進行訪問的

所以我們可以將迭代器單獨封裝成一個類去管理節點

template<class T, class Ref, class Ptr> //Ref == T& Ptr == T*
struct ListIterator //這里使用struct是因為我們要多次訪問成員,也可使用class+public
{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr) :_pNode(pNode){}ListIterator(const Self& l) :_pNode(l._pNode){}T& operator*() //解引用{return _pNode->_val;}T* operator->() {return &_pNode->_val;}Self& operator++() //前置++{_pNode = _pNode->_pNext;return *this;}Self operator++(int) //后置++{Self temp(*this);_pNode = _pNode->_pNext;return temp;}Self& operator--() //前置--{_pNode = _pNode->_pPre;return *this;}Self& operator--(int) //后置--{Self temp(*this);_pNode = _pNode->_pPre;return temp;}bool operator!=(const Self& l) //不相等判斷{return _pNode != l._pNode;}bool operator==(const Self& l) //相等判斷{return !(*this != l);}PNode _pNode;
};

?T* operator->()? 大家可能有疑惑

?當我們的節點里存的是內置類型或者STL容器是,庫里面的<<重載了這些來讀取數據

但如果是我們自己寫的類型(如class CH),<<并不能讀取該類型的數據

因此我們要取來節點自定義類的指針,來訪問該類的內部的數據(因為最底層都是內置類型

?2.1.2 迭代器的使用

 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: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);}
private:PNode _pHead;    
}

這邊我們用到了匿名對象。?

這里的const迭代器為什么不能直接用const修飾普通迭代器??

?因為typedef碰到const的話,就不是簡單的字符串替換? 實際上你以為的const T*?,在這里變成了T*const ,因為迭代器我們是希望他可以進行++和--的,而我們只是不希望他指向的內容給改變,所以我們的const要修飾的是指針的內容,而不是修飾指針。

2.2?list相關的成員函數

?2.2.1?構造函數

2.2.1.1 默認構造函數
list()
{_pHead = new Node;_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;
}    

因為無論如何都要有哨兵節點(方便我們不用判空,所以我們直接封裝一個?

void CreateHead()
{_pHead = new Node;_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;
}
?2.2.1.2 有參構造函數
 list(int n, const T& value = T()){CreateHead();for (int i = 0; i < n; ++i)push_back(value);}
?2.2.1.3 迭代器區間構造函數?
template <class Iterator>
list(Iterator first, Iterator last)
{CreateHead();while (first != last){push_back(*first);++first;}
}
2.2.1.4 拷貝構造?
1.傳統?
//拷貝構造函數傳統寫法
list(const list<T>& l)
{CreateHead();for (auto e : l)push_back(e);
}
2.現代?
void swap(list<T>& l)
{std::swap(_pHead, l._pHead);
}list(const list<T>& l)
{CreateHead();// 用l中的元素構造臨時的temp,然后與當前對象交換list<T> temp(l.begin(), l.end());swap(temp);
}

2.2.2 析構函數和clear

2.2.2.1 析構函數
~list()
{clear();delete _pHead;_pHead = nullptr;
}
2.2.2.2 clear()
void clear()
{iterator p = begin();while (p != end()){p = erase(p);}_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;
}

?2.2.3 賦值重載

list<T>& operator=(const list<T> l)
{swap(l);return *this;
}

2.2.4?修改相關函數(Modifiers)

2.2.4.1?empty、size
size_t size()const
{size_t size = 0;ListNode* p = _pHead->_pNext;while (p != _pHead){size++;p = p->_pNext;}return size;
}
bool empty()const
{return size() == 0;
}
?2.2.4.2 insert
// 在pos位置前插入值為val的節點
iterator insert(iterator pos, const T& val)
{PNode newnode = new Node(val);PNode cur = pos._pNode;PNode prev = cur->_pPre;newnode->_pPre = prev;newnode->_pNext = cur;prev->_pNext = newnode;cur->_pPre = newnode;return iterator(newnode);
}
2.2.4.3 erase?
// 刪除pos位置的節點,返回該節點的下一個位置
iterator erase(iterator pos)
{assert(pos != end());PNode prev = pos._pNode->_pPre;PNode next = pos._pNode->_pNext;prev->_pNext = next;next->_pPre = prev;delete pos._pNode;return iterator(next);//利用匿名對象返回
}
2.2.4.4 尾插尾刪頭插頭刪?
 // 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());}

2.3 反向迭代器的實現?

?sgi版本下的反向迭代器,其實就是將構建一個反向迭代器的類將正向迭代器封裝起來,這個時候正向迭代器的++就是反向迭代器的--

namespace bit
{// 適配器 -- 復用template<class Iterator, class Ref, class Ptr>   //Ref == T&  Ptr == T*struct Reverse_iterator{typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){Iterator temp = _it;--temp;return *temp;}Self& operator++(){--_it;return *this;}Self operator++(int){Iterator tmp = _it;--_it;return tmp;}Self& operator--(){++_it;return *this;}Self operator--(int){iterator temp = _it;++_it;return temp;}bool operator!=(const Self& s){return _it != s._it;}bool operator==(const Self& s){return _it == s._it;}Iterator _it;};
}

?為什么解引用的是前一個位置的元素???

?

?from?C++:List的使用和模擬實現-CSDN博客?圖來源

?

三 list模擬實現的全部代碼

#pragma once
namespace ch
{// 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>struct ListIterator{typedef ListNode<T>* PNode;typedef ListIterator<T, Ref, Ptr> Self;ListIterator(PNode pNode = nullptr) :_pNode(pNode){}ListIterator(const Self& l) :_pNode(l._pNode){}T& operator*(){return _pNode->_val;}T* operator->(){return &_pNode->_val;}Self& operator++(){_pNode = _pNode->_pNext;return *this;}Self operator++(int){Self temp(*this);_pNode = _pNode->_pNext;return temp;}Self& operator--(){_pNode = _pNode->_pPre;return *this;}Self& operator--(int){Self temp(*this);_pNode = _pNode->_pPre;return temp;}bool operator!=(const Self& l){return _pNode != l._pNode;}bool operator==(const Self& l){return !(*this != l);}PNode _pNode;};template<class Iterator, class Ref, class Ptr>   //Ref == T&  Ptr == T*struct Reverse_iterator{typedef Reverse_iterator<Iterator, Ref, Ptr> Self;Reverse_iterator(Iterator it):_it(it){}Ref operator*(){Iterator temp = _it;--temp;return *temp;}Self& operator++(){--_it;return *this;}Self operator++(int){Iterator tmp = _it;--_it;return tmp;}Self& operator--(){++_it;return *this;}Self operator--(int){iterator temp = _it;++_it;return temp;}bool operator!=(const Self& s){return _it != s._it;}bool operator==(const Self& s){return _it == s._it;}Iterator _it;};//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_iterator<iterator, T&, T*>  reverse_iterator;typedef Reverse_iterator<iterator, const T&, const T*>  const_reverse_iterator;public:///// List的構造list(){CreateHead();}list(int n, const T& value = T()){CreateHead();for (int i = 0; i < n; ++i)push_back(value);}template <class Iterator>list(Iterator first, Iterator last){CreateHead();while (first != last){push_back(*first);++first;}}list(const list<T>& l){CreateHead();// 用l中的元素構造臨時的temp,然后與當前對象交換list<T> temp(l.begin(), l.end());swap(temp);}list<T>& operator=(const list<T> l){swap(l);return *this;}~list(){clear();delete _pHead;_pHead = nullptr;}///// 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);}//反向迭代器(可讀可寫)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());}///// List Capacitysize_t size()const{size_t size = 0;ListNode* p = _pHead->_pNext;while (p != _pHead){size++;p = p->_pNext;}return size;}bool empty()const{return size() == 0;}// List AccessT& 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 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());}// 在pos位置前插入值為val的節點iterator insert(iterator pos, const T& val){PNode newnode = new Node(val);PNode cur = pos._pNode;PNode prev = cur->_pPre;newnode->_pPre = prev;newnode->_pNext = cur;prev->_pNext = newnode;cur->_pPre = newnode;return iterator(newnode);}// 刪除pos位置的節點,返回該節點的下一個位置iterator erase(iterator pos){assert(pos != end());PNode prev = pos._pNode->_pPre;PNode next = pos._pNode->_pNext;prev->_pNext = next;next->_pPre = prev;delete pos._pNode;return iterator(next);//利用匿名對象返回}void clear(){iterator p = begin();while (p != end()){p = erase(p);}_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}void swap(list<T>& l){std::swap(_pHead, l._pHead);}private:void CreateHead(){_pHead = new Node;_pHead->_pPre = _pHead;_pHead->_pNext = _pHead;}PNode _pHead;};
}

總結

???各位讀友,本篇分享到內容是否更好的讓你理解了C++的list,如果對你有幫助給個👍贊鼓勵一下吧!!
🎉🎉🎉世上沒有絕望的處境,只有對處境絕望的人。
感謝每一位一起走到這的伙伴,我們可以一起交流進步!!!一起加油吧!!。

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/web/15320.shtml
繁體地址,請注明出處:http://hk.pswp.cn/web/15320.shtml
英文地址,請注明出處:http://en.pswp.cn/web/15320.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

golang+redis的延時隊列

網址 https://github.com/cfanbo/delay-queue-redis 代碼結構很簡單&#xff0c;簡單代表著自由度很高&#xff0c;使用過程中出現問題也很好修改。 我很喜歡這樣的代碼&#xff0c;至少我看的懂&#xff0c;該有的都有。 //package main // //import ( // "context&q…

leetcode209_長度最小的子數組

要求某個連續的區間內的元素值總和>S . 思路&#xff1a;滑動窗口&#xff1a;本質上是一種雙指針法。 &#xff08;1&#xff09;初始化left right 0&#xff1b; &#xff08;2&#xff09;left不動&#xff0c;right移動&#xff0c;擴大窗口&#xff0c;直至符合要…

selinux的安全策略可以影響ntp的方式

SELinux 是一個靈活而強大的模塊化安全策略框架&#xff0c;它允許管理員定義和執行非常具體的訪問控制策略。這些策略可以限制程序和進程對系統資源的訪問&#xff0c;包括文件、網絡端口、進程間通信等。 對于NTP&#xff0c;SELinux 策略可以影響以下幾個方面&#xff1a; …

網絡空間安全數學基礎·整除與同余

主要內容&#xff1a; 整除的基本概念&#xff08;掌握&#xff09; 素數&#xff08;掌握&#xff09; 同余的概念&#xff08;掌握&#xff09; 1.1整除 定義&#xff1a;設a&#xff0c;b是任意兩個整數&#xff0c;其中b≠0&#xff0c;如果存在一個整數q&#xff0c;使 …

12306技術內幕

公司內部做的一次技術分享 文章目錄 12306的成就12306系統特點12306系統難點解決思路產品角度技術角度余票庫存的表如何設計&#xff1f; 搶票軟件推薦巨人的肩膀 對于未公開的技術部分&#xff0c;只能結合已公開的信息&#xff0c;去做大膽的猜想。 本文提到的一些解決方案&…

SpringBoot + Mybatis-Plus中樂觀鎖實現

悲觀鎖 悲觀鎖是一種悲觀思想&#xff0c;它認為數據很可能會被別人所修改 所以總會對數據進行上鎖&#xff0c;讀操作和寫操作都會上鎖&#xff0c;性能較低&#xff0c;使用較少&#xff01; 樂觀鎖 樂觀鎖是一種樂觀思想&#xff0c;它認為數據并不一定會被別人所修改 所以…

成為程序員后我都明白了什么?從入行到棄坑?

作為一個入行近10年的php程序員&#xff0c;真心感覺一切都才剛開始&#xff0c;對計算機&#xff0c;編程語言的理解也好&#xff0c;程序員中年危機也罷&#xff0c;之前都是聽別人說的&#xff0c;真的自己到了這個水平&#xff0c;這個年齡才深刻體會到這其中的種種。 我一…

測試基礎05:軟件測試的分類

課程大綱 1、兩種架構&#xff08;Architecture&#xff09; 1.1、B/S&#xff08;Browser/Server&#xff09; 瀏覽器服務器架構&#xff08;大體3步&#xff09;&#xff1a;用戶通過瀏覽器向服務器發出請求&#xff0c;服務器處理請求&#xff0c;將結果通過網絡返回到用戶…

使用Webcam實現攝像頭的開啟和關閉,并保存和復制圖片

實現思路 0&#xff0c;將webcam的jar文件傳入項目中 1&#xff0c;顯示攝像頭的地方&#xff1a;創建一個畫板&#xff0c;在畫板上添加開啟和關閉按鈕 2&#xff0c;設置開啟和關閉功能&#xff1a;創建一個類實現動作監聽器&#xff0c;進而實現監聽動作按鈕 3&#xff…

【數據結構與算法篇】二叉樹鏈式結構及實現

【數據結構與算法篇】二叉樹鏈式結構及實現 &#x1f955;個人主頁&#xff1a;開敲&#x1f349; &#x1f525;所屬專欄&#xff1a;每日刷題&#x1f34d; &#x1f33c;文章目錄&#x1f33c; 4. 二叉樹鏈式結構的實現 4.1 前置說明 4.2 二叉樹的遍歷 4.2.1 前序、中序以及…

通過ssh在本地打開遠程服務器的網頁

用途 在遠程服務器使用jupyter notebook或者tensorboard等時&#xff0c;在本地打開服務器端的網頁的方式有很多比如可以使用MobaXterm工具等&#xff0c;此方法可參考https://blog.csdn.net/cc__cc__/article/details/108060618?spm1001.2014.3001.5502。 若直接使用ssh則可…

C++感受11-Hello Object 成員版

當一個C程序員在設計類型時&#xff0c;他在想什么&#xff1f; 這一類型的對象&#xff0c;需要擁有哪些屬性數據&#xff1f;這一類型的對象&#xff0c;它將擁有哪些功能&#xff1f;這一類型的對象&#xff0c;它的各個屬性和功能之間&#xff0c;有哪些關聯關系&#xff1…

OceanBase的存儲架構與傳統LSM-Tree架構的異同|OceanBase數據轉儲合并技術解讀(二)

前篇博文將OceanBase的存儲架構巧妙地與自然界中的“水生態”進行了類比&#xff0c;今日我們轉變視角&#xff0c;聚焦在與擁有相同LSM-Tree架構的其他產品的比較&#xff0c;深入探討OceanBase相較于它們所展現出的獨特性能。 眾所周知&#xff0c;OceanBase數據庫的存儲引擎…

element-ui 前端ui框架用法開發指南(2024-05-22)

Element&#xff0c;一套為開發者、設計師和產品經理準備的基于 Vue 2.0 的桌面端組件庫 1、npm安裝 // npm安裝&#xff1a;npm install element-ui --save 能更好地和 webpack 打包工具配合使用 2、cdn在線引入 訪問最新版本的資源地址 - element-uiThe CDN for element-u…

RedHat9 | DNS剖析-配置主DNS服務器實例

一、實驗環境 1、BIND軟件包介紹 BIND軟件是一款開放源碼的DNS服務器軟件&#xff0c;由美國加州大學Berkeley分校開發和維護&#xff0c;全稱為Berkeley Internet Name Domain。該軟件在DNS&#xff08;域名系統&#xff09;領域具有重要地位&#xff0c;是目前世界上使用最…

使用OpenCV dnn c++加載YOLOv8生成的onnx文件進行目標檢測

在網上下載了60多幅包含西瓜和冬瓜的圖像組成melon數據集&#xff0c;使用 LabelMe 工具進行標注&#xff0c;然后使用 labelme2yolov8 腳本將json文件轉換成YOLOv8支持的.txt文件&#xff0c;并自動生成YOLOv8支持的目錄結構&#xff0c;包括melon.yaml文件&#xff0c;其內容…

信息系統管理工程師問答題

信息系統管理工程師問答題 系統管理安全兩方面 安全測試 入侵檢測系統的功能 用戶標識與驗證常用的3種方法 (1) 要求用戶輸入一些保密信息&#xff0c;例如用戶名稱和密碼&#xff1b; (2) 采用物理識別設備&#xff0c;例如訪問卡、鑰匙或令牌&#xff1b; (3) 采用生物統計學…

Python怎樣定位并刪除Sql語句中不確定的查詢條件

1.問題場景描述: 在sql語句中經常會有查詢條件是:查找多個訂單簽訂日期范圍的數據,但具體的日期范圍是不確定,我們如何來查找定位 例如:查詢條件語句的部分如下圖: 目標是: 1)定位字符串:t_contract_order.sign_date 2)最終得到結果: 解決問題思路: 1)定位要找的字符串起始位置…

【學習心得】PyTorch的知識要點復習(持續更新)

PyTorch知識要點復習&#xff0c;目的是為了鞏固PyTorch基礎、快速回顧、深化理解PyTorch框架。這篇文章會持續更新。 一、本文的一些說明 知識點梳理&#xff1a;我將PyTorch的核心概念和高級技巧進行了系統化的整理&#xff0c;從基礎的張量操作到復雜的模型構建與訓練。這樣…

【Linux】進程終止與進程等待

目錄 進程終止 errno exit和_exit 進程等待 wait和waitpid 宏&#xff1a;WIFEXITED 非阻塞等待 進程終止 下面要談的一個話題就是進程終止&#xff0c;就是說一個進程退出了&#xff0c;可能有三種情況 1.進程代碼執行完&#xff0c;結果是正確的 2.進程代碼執行完&…