vector使用以及模擬實現

vector使用以及模擬實現

    • vector介紹
    • vector常用接口
      • 1.構造
      • 2.迭代器
      • 3.容量
      • 4.增刪查改
      • 5.練習
    • vector模擬實現
      • 1.迭代器失效
      • 2.反向迭代器
      • 3.完整代碼

vector介紹

  1. 和我們原來講的string不同,vector并不是類,是一個類模板,加<類型>實例化以后才是類。
  2. vector是表示可變大小數組的序列容器。
  3. 像數組一樣,vector也采用的連續存儲空間來存儲元素,但是容量可以動態改變。
  4. 和其它容器相比,vector訪問元素、尾插、尾刪較高效,但不在尾部的插入和刪除效率比較低,需要頻繁插入和刪除的話不建議使用vector



vector常用接口

1.構造

函數聲明功能
vector()(常用)無參構造
vector
(size_type n, const value_type& val = value_type())
構造并初始化n個val
vector (const vector& x)(常用)拷貝構造
vector (InputIterator first, InputIterator last)迭代器區間初始化
(模板,可以傳入其它容器的迭代器區間)

2.迭代器

函數聲明功能
begin()加end() (常用)獲取第一個數據位置的iterator/const_iterator,獲取最后一個數據的下一個位置的iterator/const_iterator
rbegin()加rend()反向迭代器,獲取最后一個數據位置的reverse_iterator,獲取第一個數據前一個位置的reverse_iterator

3.容量

函數聲明功能
size() (常用)獲取數據個數
capacity()獲取容器容量
empty()判斷是否為空(size為0為空,返回true)
resize(size_type n, value_type val = value_type())?????1.n>size()時從尾開始填充val直到容器滿;
2.n>容量就先擴容再填充;
?????3.n<size()時縮小size(),保留前n個。
reserve(size_t n = 0)預留空間,n大于容量時擴容,不然什么都不做

4.增刪查改

函數聲明功能
push_back (const value_type& val)(常用)尾插
pop_back()(常用)尾刪
find (InputIterator first, InputIterator last, const T& val)不是vector接口,是算法庫里面的模板,傳入一段迭代器區間,可以在該區間查找val
insert (iterator position, const value_type& val)在position前插入val
erase (iterator position)刪除position位置的數據
swap (vector& x)交換兩個vector的數據空間
operator[] (size_type n)像數組一樣訪問數據

5.練習

  • 只出現一次的數字i

題目要求:
在這里插入圖片描述

題解:

class Solution 
{
public:int singleNumber(vector<int>& nums) {//這個題需要異或這個位運算//異或是相同為0,不同為1。//所以兩個相同的數異或會得到0//0和任何數異或都得到這個數本身//題目明確了只有一個數出現一次,其它都出現兩次//因此我們可以把所有數異或一次,出現兩次的數字會抵消變成0//最后出現一次的數字一定可以留下來int end = 0;vector<int>::iterator it = nums.begin();//auto it = nums.begin();while(it != nums.end()){end ^= *it;it++;}//范圍for同理// for(auto ch : nums)//     end ^= ch;return end;}
};


  • 刪除排序數組中的重復項

題目要求:
在這里插入圖片描述


題解:
在這里插入圖片描述

class Solution {
public:int removeDuplicates(vector<int>& nums) {int sum = 1;int slow = 1;int fast = 1;//快慢指針while(fast < nums.size()){if(nums[fast] > nums[fast-1]){nums[slow++] = nums[fast++];sum++;}else{fast++;}}return sum;        }
};


  • 楊輝三角

題目要求:
在這里插入圖片描述

題解:
在這里插入圖片描述

class Solution {
public:vector<vector<int>> generate(int numRows) {vector<vector<int>> vv;//把size調整為numRowsvv.resize(numRows);for(int i = 0; i < numRows; i++){vv[i].resize(i+1,0);//每一行最后一個和第一個初始為1vv[i][0] = vv[i][vv[i].size()-1] = 1;}for(int i = 0; i < numRows; i++){for(int j = 0; j < vv[i].size(); j++){if(vv[i][j] == 0)                vv[i][j] = vv[i-1][j] + vv[i-1][j-1];                }}return vv;}
};



vector模擬實現

1.迭代器失效

??????迭代器的主要作用就是讓算法能夠不用關心底層數據結構,而vector迭代器的底層實際是一個指針,在對容器進行操作(例如插入、刪除、修改等)后,之前獲取的迭代器可能會變得無效


可能會導致其迭代器失效的操作有:
  1. 會引起其底層空間改變的操作(擴容),都有可能是迭代器失效,比如:resize、reserve、insert、push_back等。
#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1,2,3,4,5,6 };auto it = v.begin();// 將有效元素個數增加到100個,多出的位置使用8填充,操作期間底層會擴容// v.resize(100, 8);// reserve的作用就是改變擴容大小但不改變有效元素個數,操作期間可能會引起底層容量改變// v.reserve(100);// 插入元素期間,可能會引起擴容,而導致原空間被釋放// v.insert(v.begin(), 0);// v.push_back(8);// 給vector重新賦值,可能會引起底層容量改變v.assign(100, 8);/*出錯原因:以上操作,都有可能會導致vector擴容,也就是說vector底層舊空間被釋放掉,而在打印時,it還使用的是釋放之間的舊空間,在對it迭代器操作時,實際操作的是一塊已經被釋放的空間,而引起代碼運行時崩潰。解決方式:在以上操作完成之后,如果想要繼續通過迭代器操作vector中的元素,只需給it重新賦值即可。*/while (it != v.end()){cout << *it << " ";++it;}cout << endl;return 0;
}

  1. 指定位置元素的刪除操作–erase

在這里插入圖片描述

#define _CRT_SECURE_NO_WARNINGS 1
#include <iostream>
using namespace std;
#include <vector>
int main()
{vector<int> v{ 1,2,3,4,5,6 };//earse不會影響底層的空間(不進行擴容和縮容)//但是也存在迭代器失效的問題//下面這段代碼用來刪除v中的偶數auto it = v.begin();while (it != v.end()){if (*it % 2 == 0) {//把這個位置數據刪除掉v.erase(it);}it++;}//結果:程序崩潰//原因:看圖解,erase是會改變end()的//解決方法:每次erase操作后都及時更新迭代器//erase會返回被刪除數據下一位置的迭代器//auto it = v.begin();//while (it != v.end())//{//	if (*it % 2 == 0)//	{//		//把這個位置數據刪除掉//		it = v.erase(it);//	}//	else//	{//		it++;//	}//}return 0;
}

2.反向迭代器

??????vector的反向迭代器實現并不困難,只需要復用普通的迭代器,++操作變成調用普通迭代器的–,–調用++即可。

// 反向迭代器需要進行封裝,其實就是復用普通迭代器,然后++和--操作反過來
//這里設計模板參數除了迭代器,還有Ref(引用)和Ptr(指針)
//這樣設計是為了同時生成普通迭代器和const對象的迭代器//普通對象(可讀可寫):Reverse_iterator<iterator,T&,T*>
//const對象(可讀不可寫):Reverse_iterator<const_iterator,const T&,const T*>
template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{//給自己也重命名一下,方便用typedef Reverse_iterator<Iterator, Ref, Ptr> self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}self& operator++(){_it--;return *this;}self operator++(int){self tmp(*this);_it--;return tmp;}self& operator--(){_it++;return *this;}self operator--(int){self tmp(*this);_it++;return tmp;}Ref operator*(){return *_it;}//返回指針可以讓自定義類型自行打印,訪問成員//->操作符,比較特殊,it->_num轉換出來其實是it.operator->()->_numPtr operator->(){return _it;}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}
};

3.完整代碼

采用三個迭代器(指針)來維護底層空間:

private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;

在這里插入圖片描述


#pragma once
#include<iostream>
#include<assert.h>
//#include<vector>
using namespace std;//和庫里面的區分開
namespace MyVector
{// 反向迭代器需要進行封裝,其實就是復用普通迭代器,然后++和--操作反過來//這里設計模板參數除了迭代器,還有Ref(引用)和Ptr(指針)//這樣設計是為了同時生成普通迭代器和const對象的迭代器//普通對象(可讀可寫):Reverse_iterator<iterator,T&,T*>//const對象(可讀不可寫):Reverse_iterator<const_iterator,const T&,const T*>template<class Iterator, class Ref, class Ptr>struct Reverse_iterator{//給自己也重命名一下,方便用typedef Reverse_iterator<Iterator, Ref, Ptr> self;Iterator _it;Reverse_iterator(Iterator it):_it(it){}self& operator++(){_it--;return *this;}self operator++(int){self tmp(*this);_it--;return tmp;}self& operator--(){_it++;return *this;}self operator--(int){self tmp(*this);_it++;return tmp;}Ref operator*(){return *_it;}//返回指針可以讓自定義類型自行打印,訪問成員//->操作符,比較特殊,it->_num轉換出來其實是it.operator->()->_numPtr operator->(){return _it;}bool operator!=(const self& s){return _it != s._it;}bool operator==(const self& s){return _it == s._it;}};//vector類模板template <typename T>class vector{public:typedef T* iterator;typedef const T* const_iterator;typedef Reverse_iterator<iterator, T&, T*> reverse_iterator;typedef Reverse_iterator< const_iterator, const T&,const T*> reverse_const_iterator;iterator begin(){//隱式類型轉換return _start;}iterator end(){return _finish;}const_iterator begin()const{return _start;}const_iterator end()const{return _finish;}reverse_iterator rbegin(){return  _finish-1;}reverse_iterator rend(){return _start-1;}reverse_const_iterator rbegin()const{return _finish-1;}reverse_const_iterator rend()const{return _start-1;}/////無參構造vector(){}//函數模板,傳入容器的一段迭代器區間template <typename InputIterator>vector(InputIterator first, InputIterator last){while (first != last){push_back(*first);first++;}}//構造vector(const vector<T>& v){//提前開好空間reverse(v.capacity());for (auto& e : v){push_back(e);}}vector(size_t n, const T& val = T()){reverse(n);for (size_t i = 0; i < n; i++){push_back(val);}}//重載給內置類型使用//沒有的話vector<int> v(5,0)會優先和vector(InputIterator first, InputIterator last)匹配//對整形解引用會報錯vector(int n, const T& val = T()){reverse(n);for (int i = 0; i < n; i++){push_back(val);}}~vector(){delete[] _start;_start = _finish = _endofstorage = nullptr;}void swap(vector<T>& v){std::swap(_start, v._start);std::swap(_finish, v._finish);std::swap(_endofstorage, v._endofstorage);}//傳值傳參,拷貝一份,直接交換操作的空間即可vector<T>& operator=(vector<T> v){swap(v);return *this;}/// ///void reverse(size_t n){if (n > capacity()){//這里擴容空間會變化,先記錄size//這里擴容空間會變化,先記錄size//這里擴容空間會變化,先記錄sizesize_t sz = size();T* tmp = new T[n];//這里涉及到深淺拷貝for (size_t i = 0; i < sz; i++){tmp[i] = _start[i];}delete[] _start;_start = tmp;_finish = _start + sz;_endofstorage = _start + n;}}void resize(size_t n, const T& val = T()){if (n <= size()){_finish = _start + n;}else{//先擴容reverse(n);while (_finish < _start + n){*_finish = val;_finish++;}}}T& operator[](size_t pos){assert(pos < size());return _start[pos];}const T& operator[](size_t pos)const{assert(pos < size());return _start[pos];}size_t capacity()const{return _endofstorage - _start;}size_t size()const{return _finish - _start;}/// ///void push_back(const T& x){//復用即可insert(end(), x);}void insert(iterator pos, const T& x){assert(pos <= _finish && pos >= _start);if (_finish == _endofstorage){size_t gap = pos - _start;//初始擴容需要指定給reverse(capacity() == 0 ? 4 : 2 * capacity());pos = _start + gap;}iterator end = _finish;while (end > pos){*end = *(end - 1);end--;}*pos = x;_finish++;			}iterator erase(iterator pos){assert(pos < _finish&& pos >= _start);iterator it = pos + 1;while (it < _finish){*(it - 1) = *it;it++;}_finish--;return pos;}private:iterator _start = nullptr;iterator _finish = nullptr;iterator _endofstorage = nullptr;};}

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

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

相關文章

主機防護的重要性和方式

01 主機防護的重要性 主機防護是網絡安全的重要組成部分。在互聯網時代&#xff0c;網絡攻擊成為了一種常見的威脅&#xff0c;而主機防護則是保護計算機系統免受網絡攻擊的重要手段。 主機防護可以防范各種網絡攻擊&#xff0c;如病毒、木馬、黑客攻擊等&#xff0c;從而保…

氣象監測站:用科技感知氣象變化

氣象監測站是利用科學技術感知當地小氣候變化情況的氣象觀測儀器&#xff0c;可用于農業、林業、養殖業、畜牧業、環境保護、工業等多個領域&#xff0c;提高對環境數據的利用率&#xff0c;促進產業效能不斷提升。 氣象監測站主要由氣象傳感器、數據傳輸系統、電源系統、支架…

Linux debian12解壓和壓縮.rar文件教程

一、Debian12安裝rar命令 sudo apt install rar二、使用rar軟件 1.解壓文件 命令格式&#xff1a; rar x 文件名.rar實力測試&#xff1a; [rootdoudou tmp]# rar x test.rar2.壓縮文件 test是一個文件夾 命令格式&#xff1a; rar a 文件名.rar 文件夾名實例測試&#x…

centos7 yum獲取軟件所有依賴包 創建本地yum源 yum離線安裝軟件

centos7 yum獲取軟件所有依賴包 創建本地yum源 離線安裝軟件 1、以安裝docker 20.10為例2、centos7 yum獲取docker 20.10 所有依賴包3、創建本地docker yum源4、yum使用本地docker源 離線安裝docker 1、以安裝docker 20.10為例 參考鏈接&#xff1a; 添加docker 清華軟件源 y…

git環境超詳細配置說明

一&#xff0c;簡介 在git工具安裝完成之后&#xff0c;需要設置一下常用的配置&#xff0c;如郵箱&#xff0c;縮寫&#xff0c;以及git commit模板等等。本文就來詳細介紹些各個配置如何操作&#xff0c;供參考。 二&#xff0c;配置步驟 2.1 查看當前git的配置 git conf…

使用 Apache Kafka 和 Go 將數據引入 OpenSearch

需要編寫自定義集成層來滿足數據管道中的特定要求&#xff1f;了解如何使用 Go 通過 Kafka 和 OpenSearch 實現此目的。 可擴展的數據攝取是OpenSearch等大規模分布式搜索和分析引擎的一個關鍵方面。構建實時數據攝取管道的方法之一是使用Apache Kafka。它是一個開源事件流平臺…

單詞倒排(C語言詳解)

題目&#xff1a;單詞倒排 描述&#xff1a;對字符串中的所有單詞進行倒排。 說明&#xff1a; 1、構成單詞的字符只有26個大寫或小寫英文字母&#xff1b; 2、非構成單詞的字符均視為單詞間隔符&#xff1b; 3、要求倒排后的單詞間隔符以一個空格表示&#xff1b;如果原字…

米爾瑞薩RZ/G2L開發板-02 ffmpeg的使用和RTMP直播

最近不知道是不是熬夜太多&#xff0c;然后記憶力減退了&#xff1f; 因為板子回來以后我就迫不及待的試了一下板子&#xff0c;然后發現板子有SSH&#xff0c;但是并沒有ffmpeg&#xff0c;最近總是在玩&#xff0c;然后今天說是把板子還原一下哇&#xff0c;然后把官方的固件…

前端單點登錄SSO面試回答

JWT鑒權機制 1.JWT用于登錄身份驗證 2.用戶登錄成功后&#xff0c;后端通過JWT機制生成一個token&#xff0c;返回給客戶端 3.客戶端后續的每次請求都需要攜帶token&#xff0c;放在header的authorization中 4.后端從authorization中拿到token后&#xff0c;通過secretKey進…

Spring Boot中使用validator如何實現接口入參自動檢驗

文章目錄 一、背景二、使用三、舉例 一、背景 在項目開發過程中&#xff0c;經常會對一些字段進行校驗&#xff0c;比如字段的非空校驗、字段的長度校驗等&#xff0c;如果在每個需要的地方寫一堆if else 會讓你的代碼變的冗余笨重且相對不好維護&#xff0c;如何更加規范和優…

微服務-GateWay(網關)

所謂網關是什么意思&#xff1f; 相當于就是你們小區家的保安&#xff0c;進出小區都得獲得保安的同意&#xff0c;守護你們小區的生命財產健康&#xff0c;網關也是如此&#xff0c;對每個請求都嚴格把關&#xff0c;將合法的或者是獲得權限的請求進入服務器 網關的功能&…

設計模式之解釋器模式詳解及實例

1、解釋器設計模式概述&#xff1a; 解釋器模式&#xff08;Interpreter Pattern&#xff09;是一種設計模式&#xff0c;它主要用于描述如何構建一個解釋器以解釋特定的語言或表達式。該模式定義了一個文法表示和解釋器的類結構&#xff0c;用于解釋符合該文法規則的語句。解…

擴散模型實戰(四):從零構建擴散模型

推薦閱讀列表&#xff1a; 擴散模型實戰&#xff08;一&#xff09;&#xff1a;基本原理介紹 擴散模型實戰&#xff08;二&#xff09;&#xff1a;擴散模型的發展 擴散模型實戰&#xff08;三&#xff09;&#xff1a;擴散模型的應用 本文以MNIST數據集為例&#xff0c;從…

智能樓宇綜合布線實訓室建設方案

一、樓宇智能綜合布線實訓室方案概述 樓宇智能綜合布線實訓室方案旨在為學生提供一個真實的學習和實踐環境&#xff0c;以培養他們在樓宇智能綜合布線領域的實際操作能力和技能。以下是一個概述&#xff1a; 1. 培養目標&#xff1a;培養學生在樓宇智能綜合布線方面的綜合能力…

Shader學習(三)(片元著色器)

1、在片元著色器處理漫反射 // Upgrade NOTE: replaced _World2Object with unity_WorldToObjectShader "Custom/specularfragement" {properties{_sp("Specular",color) (1,1,1,1)_shiness("Shiness",range(1,64)) 8}SubShader{pass {tags{&…

深入理解設計模式-行為型之模板(和回調區別聯系)

概述 模板設計模式&#xff08;Template Design Pattern&#xff09;是一種行為型設計模式&#xff0c;它定義了一個算法的骨架&#xff0c;將算法的一些步驟延遲到子類中實現。模板設計模式允許子類在不改變算法結構的情況下重新定義算法的某些步驟。 模板設計模式的核心思想…

網絡通信原理應用層(第五十一課)

1)DNS:域名解析系統,端口號TCP或UDP的53 2)域名注冊網站 -新網 www.xinnet.com -萬網-阿里云 www.net.cn -中國互聯 hulian.top 配置通過域名訪問網站(NETBASE第七課)_IHOPEDREAM的博客-CSDN博客 2、FTP 1)FTP概述 -文件傳輸協議 -控制連接:TCP 21 <

對redis、redisson、springcache總結

<一> redis-緩存中間件 什么是redis redis是c語言開發的&#xff0c;一個高性能key-value鍵值對內存數據庫&#xff0c;可以用來做數據庫、緩存、消息中間件的一種非關系型數據庫。 redis數據存儲在哪里 內存和磁盤中&#xff0c;但是redis的讀寫都在內存中&#xff0c;…

leetcode-413. 等差數列劃分(java)

等差數列劃分 leetcode-413. 等差數列劃分題目描述雙指針 上期經典算法 leetcode-413. 等差數列劃分 難度 - 中等 原題鏈接 - 等差數列劃分 題目描述 如果一個數列 至少有三個元素 &#xff0c;并且任意兩個相鄰元素之差相同&#xff0c;則稱該數列為等差數列。 例如&#xff0…

16 腦洞大開:GUI測試還能這么玩

頁面對象自動生成技術 頁面對象自動生成技術&#xff0c;屬于典型的“自動化你的自動化”的應用場景。它的基本思路是&#xff0c;你不用再手工維護 Page Class 了&#xff0c;只需要提供 Web 的 URL&#xff0c;它就會自動幫你生成這個頁面上所有控件的定位信息&#xff0c;并…