国产 无码 综合区,色欲AV无码国产永久播放,无码天堂亚洲国产AV,国产日韩欧美女同一区二区

【C++】學(xué)習(xí)STL中的list

這篇具有很好參考價(jià)值的文章主要介紹了【C++】學(xué)習(xí)STL中的list。希望對大家有所幫助。如果存在錯(cuò)誤或未考慮完全的地方,請大家不吝賜教,您也可以點(diǎn)擊"舉報(bào)違法"按鈕提交疑問。

??前言

? ? ? ? 大家好!,今天為大家?guī)淼囊黄┛褪顷P(guān)于STL中的list,內(nèi)容主要包括list的介紹使用、list的模擬實(shí)現(xiàn)。以及l(fā)ist與vector的對比。

正文

list的介紹和使用

? ? ? ? 首先,讓我們看看list的文檔介紹:

  1. list是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。
  2. list的底層是雙向鏈表結(jié)構(gòu),雙向鏈表中每個(gè)元素存儲(chǔ)在互不相關(guān)的獨(dú)立節(jié)點(diǎn)中,在節(jié)點(diǎn)中通過指針指向其前一個(gè)元素和后一個(gè)元素。
  3. list與forward_list非常相似:最主要的不同在于forward_list是單鏈表,只能朝前迭代,已讓其更簡單高效。
  4. 與其他的序列式容器相比(array,vector,deque),list通常在任意位置進(jìn)行插入、移除元素的執(zhí)行效率更好。
  5. 與其他序列式容器相比,list和forward_list最大的缺陷是不支持任意位置的隨機(jī)訪問,比如:要訪問list的第6個(gè)元素,必須從已知的位置(比如頭部或者尾部)迭代到該位置,在這段位置上迭代需要線性的時(shí)間開銷;list還需要一些額外的空間,以保存每個(gè)節(jié)點(diǎn)的相關(guān)聯(lián)信息(對于存儲(chǔ)類型較小元素的大list來說這可能是一個(gè)重要的因素)

? ? ? ? 官方網(wǎng)站list的文檔介紹如下:

list - C++ Reference (cplusplus.com)https://legacy.cplusplus.com/reference/list/list/?kw=list? ? ? ? list的簡單使用在我們學(xué)會(huì)了vector的使用之后只要多看看list的文檔并多加使用就可以很熟悉,因此在這里就不多講了。

? ? ? ? 需要提一提的是,由于存儲(chǔ)在其中的元素的內(nèi)存并不是連續(xù)的,list并不支持隨機(jī)訪問,也沒有提供重載方括號。并且因此它并不適合算法庫中的sort()和reverse(),于是在我們想要對list進(jìn)行排序或者逆置的時(shí)候,應(yīng)該使用list自帶的接口,它們的名字與算法庫中的一樣。

? ? ? ? 除此之外,使用list時(shí)也可能遇到迭代器失效的問題,這時(shí)候我們需要重新為迭代器賦值來解決這個(gè)問題。

list的模擬實(shí)現(xiàn)

? ? ? ? list的模擬實(shí)現(xiàn)分為三個(gè)部分,分別為:list的節(jié)點(diǎn)、list的迭代器、list本體。

list_node的模擬實(shí)現(xiàn)

? ? ? ? 首先我們模擬實(shí)現(xiàn)list的節(jié)點(diǎn),雙向鏈表需要節(jié)點(diǎn)具有前后兩個(gè)指針:

template<typename T>
struct list_node
{
    // 我們初學(xué)類模板時(shí)常常會(huì)忘記寫<T>
    // 這里需要注意,模板名帶上尖括號之后才會(huì)成為類型名
	list_node<T>* _prev;
	list_node<T>* _next;
	T _val;

	list_node<T>(const T& x = T())
		:_prev(nullptr)
		,_next(nullptr)
		,_val(x)
	{}
};

list迭代器的模擬實(shí)現(xiàn)

? ? ? ? 然后我們要接著模擬實(shí)現(xiàn)list的迭代器,這里我們有一個(gè)很重要的設(shè)計(jì),就是設(shè)置多個(gè)模板參數(shù),對應(yīng)數(shù)據(jù)類型,數(shù)據(jù)的引用類型,數(shù)據(jù)的指針類型。

? ? ? ? 設(shè)計(jì)的思路:當(dāng)我們設(shè)計(jì)迭代器類的時(shí)候,不僅要考慮普通的迭代器,還要考慮const迭代器,它并不是簡單的在迭代器類聲明對象前加上const關(guān)鍵字就可以。因?yàn)槲覀兊腸onst迭代器并不意味著我們不能改動(dòng)這個(gè)迭代器對象本身,而是我們不能改動(dòng)此迭代器所指向的數(shù)據(jù)。因此我們需要對迭代器類的一些接口的返回值類型做改動(dòng),也就是 * 號和 -> ,原因是這兩個(gè)重載運(yùn)算符會(huì)提供操作數(shù)據(jù)的方式。這種設(shè)計(jì)很好的減少了代碼的冗余,使我們不用再另寫一份const迭代器。

? ? ? ? 除此之外,迭代器實(shí)現(xiàn)中比較獨(dú)特的一點(diǎn)就是->運(yùn)算符的重載,我們可以看到這里的運(yùn)算符重載返回值為節(jié)點(diǎn)值的地址,那么我們獲得了節(jié)點(diǎn)數(shù)據(jù)的地址之后繼續(xù)要訪問節(jié)點(diǎn)值的成員,應(yīng)該要再使用一次->運(yùn)算符,那么在具體應(yīng)用中我們就需要使用兩個(gè)箭頭,也就是 iterator->->member ,但是這不符合我們使用->運(yùn)算符的習(xí)慣,于是編譯器就為我們簡化了一下,只要使用一次箭頭,編譯器自己會(huì)正確識別這樣的寫法。

	template<typename T, typename Ref, typename Ptr>
	struct _list_iterator
	{
		typedef list_node<T> Node;
		typedef _list_iterator<T, Ref, Ptr> self;

		Node* _node;

		_list_iterator(Node* node)
			:_node(node)
		{}

		Ref operator*()
		{
			return _node->_val;
		}

		Ptr operator->()
		{
			return &_node->_val;
		}

		self& operator++()
		{
			_node = _node->_next;
			return *this;
		}

		self operator++(int)
		{
			_node = _node->_next;
			return _node->_prev;
		}

		self& operator--()
		{
			_node = _node->_prev;
			return *this;
		}

		self operator--(int)
		{
			_node = _node->_prev;
			return _node->_next;
		}

		bool operator!=(const self& it) const
		{
			return _node != it._node;
		}

		bool operator==(const self& it) const
		{
			return _node == it._node;
		}
	};

? ? ? ? ? ? ? ?除了正向迭代器之外,我們還有一個(gè)反向迭代器,反向迭代器的使用規(guī)則與正向迭代器完全相反,如果我們直接重新定義一個(gè)反向迭代器的類模板,那么我們就需要為每一種迭代器都再寫一份反向迭代器,這樣代碼會(huì)非常的冗余。于是這里就引出了一個(gè)新的概念——適配器模式。

? ? ? ? 由于反向迭代器的規(guī)則與迭代器完全相反,反向迭代器的許多地方其實(shí)是可以復(fù)用對應(yīng)正向迭代器本身的接口。那么我們就將迭代器類型作為一個(gè)模板參數(shù)傳入,然后在反向迭代器內(nèi)部創(chuàng)建一個(gè)正向迭代器,之后就可以直接對其進(jìn)行相反的操作,這樣我們就得到了一個(gè)可以復(fù)用的反向迭代器模板。代碼如下:

template<class Iterator, class Ref, class Ptr>
struct Reverse_iterator
{
	typedef Reverse_iterator<Iterator, Ref, Ptr> self;

	Reverse_iterator(Iterator it)
		:_it(it)
	{}

	Ref operator*()
	{
		return *_it;
	}
		
	Ptr operator->()
	{
		return &_it->_node->_val;
	}

	self& operator++()
	{
		return --_it;
	}

	self operator++(int)
	{
		return _it--;
	}

	self& operator--()
	{
		return ++_it;
	}

	self operator--(int)
	{
		return _it++;
	}

	bool operator!=(const self& rit) const
	{
		return _it != rit._it;
	}
		
	bool operator==(const self& rit) const
	{
		return _it == rit._it;
	}

private:
	Iterator _it;
};

list本身的實(shí)現(xiàn)

? ? ? ? list本身的實(shí)現(xiàn)非常簡單,我們之前在數(shù)據(jù)結(jié)構(gòu)時(shí)期已經(jīng)學(xué)過了鏈表的相關(guān)知識,寫個(gè)雙向循環(huán)鏈表應(yīng)該是不在話下。簡單代碼如下:

template<typename T>
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 Reverse_iterator<iterator, T&, T*> reverse_iterator;

	reverse_iterator rbegin()
	{
		return (iterator)_head->_prev;
	}

	reverse_iterator rend()
	{
		return (iterator)_head;
	}

	iterator begin()
	{
		return _head->_next;
	}

	iterator end()
	{
		return _head;
	}

	const_iterator begin() const
	{
		return _head->_next;
	}

	const_iterator end() const
	{
		return _head;
	}

	list<T>()
	{
		_head = new Node;
		_head->_next = _head;
		_head->_prev = _head;
	}

	list<T>(const list<T>& lt)
	{
		_head = new Node;
		_head->_next = _head;
		_head->_prev = _head;

		for (auto& x : lt)
		{
			push_back(x);
		}
	}

	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;
	}

    // 復(fù)用insert的代碼
	void push_back(const T& x)
	{
		//Node* tail = _head->_prev;
		//Node* newnode = new Node(x);

		//newnode->_next = tail->_next;
		//newnode->_prev = tail;

		//tail->_next = newnode;
		//_head->_prev = newnode;
		//_size++;

		insert(end(), x);
	}

    // 復(fù)用erase的代碼
	void pop_back()
	{
		//Node* tail = _head->_prev;
		//Node* nexttail = tail->_prev;

		//_head->_prev = nexttail;
		//nexttail->_next = _head;
		//delete tail;
		//_size--;

		erase(--end());
	}

	void push_front(const T& x)
	{
		insert(begin(), x);
	}

	void pop_front()
	{
		erase(begin());
	}

	// pos之前位置插入
	iterator insert(iterator pos, const T& x)
	{
		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* newnode = new Node(x);

		newnode->_prev = prev;
		newnode->_next = cur;

		prev->_next = newnode;
		cur->_prev = newnode;

		_size++;

		return newnode;
	}

	iterator erase(iterator pos)
	{
		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* next = cur->_next;

		prev->_next = next;
		next->_prev = prev;
			
		delete cur;
		_size--;

		return next;
	}

	size_t size()
	{
		return _size;
	}

	void clear()
	{
		auto it = begin();
		while (it != end())
		{
			it = erase(it);
		}
	}

	~list<T>()
	{
		clear();

		delete _head;
		_head = nullptr;
	}

private:
	Node* _head;
	size_t _size = 0;
};

list和vector的對比

? ? ? ? list和vector的底層數(shù)據(jù)結(jié)構(gòu)分別是鏈表和數(shù)組,它們的區(qū)別也就是鏈表與數(shù)組的區(qū)別。它們之間的不同點(diǎn)如下:

  • list的迭代器不支持隨機(jī)訪問和加減等操作,但是vector的迭代器支持
  • list的內(nèi)存空間不是連續(xù)的,而vector的內(nèi)存空間是連續(xù)的
  • list在中間和開頭插入刪除的效率要比vector高得多
  • list的查詢效率較低

? ? ? ? 總的來說,這兩種容器各有優(yōu)缺點(diǎn),我們要根據(jù)使用場景進(jìn)行靈活選擇。

??結(jié)語

? ? ? ? ok,那么這篇拖了許久的博客也終于是寫完了,臨近開學(xué),希望大家開學(xué)快樂呀!文章來源地址http://www.zghlxwxcb.cn/news/detail-691992.html

到了這里,關(guān)于【C++】學(xué)習(xí)STL中的list的文章就介紹完了。如果您還想了解更多內(nèi)容,請?jiān)谟疑辖撬阉鱐OY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

本文來自互聯(lián)網(wǎng)用戶投稿,該文觀點(diǎn)僅代表作者本人,不代表本站立場。本站僅提供信息存儲(chǔ)空間服務(wù),不擁有所有權(quán),不承擔(dān)相關(guān)法律責(zé)任。如若轉(zhuǎn)載,請注明出處: 如若內(nèi)容造成侵權(quán)/違法違規(guī)/事實(shí)不符,請點(diǎn)擊違法舉報(bào)進(jìn)行投訴反饋,一經(jīng)查實(shí),立即刪除!

領(lǐng)支付寶紅包贊助服務(wù)器費(fèi)用

相關(guān)文章

  • 【C++】學(xué)習(xí)C++STL中的數(shù)組——vector

    【C++】學(xué)習(xí)C++STL中的數(shù)組——vector

    ? ? ? ? 好久不見大家!今天的這篇博客是關(guān)于我對于STL(C++標(biāo)準(zhǔn)模板庫)中的容器vector的學(xué)習(xí)和理解,希望大家能夠喜歡。 ? ? ? ? ?vector是STL中的一種序列容器,對應(yīng)著數(shù)據(jù)結(jié)構(gòu)中的順序表,也可以說是數(shù)組。在我們正式學(xué)習(xí)了解vector之前,我們先看看C++官網(wǎng)對其的文檔介

    2024年02月10日
    瀏覽(19)
  • 【041】從零開始:逐步學(xué)習(xí)使用C++ STL中的stack容器

    【041】從零開始:逐步學(xué)習(xí)使用C++ STL中的stack容器

    ?? 作者簡介:一個(gè)熱愛分享高性能服務(wù)器后臺開發(fā)知識的博主,目標(biāo)是通過理論與代碼實(shí)踐的結(jié)合,讓世界上看似難以掌握的技術(shù)變得易于理解與掌握。技能涵蓋了多個(gè)領(lǐng)域,包括C/C++、Linux、Nginx、MySQL、Redis、fastdfs、kafka、Docker、TCP/IP、協(xié)程、DPDK等。 ?? ??? CSDN實(shí)力新星

    2024年02月16日
    瀏覽(23)
  • C++:STL--List

    C++:STL--List

    STL容器的代碼設(shè)計(jì)中, 模板編程 和 代碼復(fù)用的思想貫穿始終 ,代碼復(fù)用可以將各個(gè)成員接口統(tǒng)一起來從而 大大增加程序的可讀性和可維護(hù)性 ,模板編程使得容器類可以 根據(jù)需要用于存儲(chǔ)各種不同類型的數(shù)據(jù) . C++STL標(biāo)準(zhǔn)庫中的list使用的數(shù)據(jù)結(jié)構(gòu)是帶頭雙向循環(huán)鏈表 ; 鏈表的頭

    2024年02月10日
    瀏覽(24)
  • C++ STL list

    C++ STL list

    ?1主頁:我的代碼愛吃辣 ??2知識講解:C++之 STL list介紹和模擬實(shí)現(xiàn) ??3開發(fā)環(huán)境:Visual Studio 2022 ??4前言:上次我們詳細(xì)的介紹了vector,今天我們繼續(xù)來介紹一下TSTL中的另外一個(gè)容器list。list在基礎(chǔ)的功能和結(jié)構(gòu)上就是一個(gè)雙向帶頭的循環(huán)鏈表,實(shí)現(xiàn)起來基本不難,但是

    2024年02月13日
    瀏覽(24)
  • 【C++】STL---list

    【C++】STL---list

    list 是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。 list 的底層是 雙向鏈表 結(jié)構(gòu),雙向鏈表中每個(gè)元素存儲(chǔ)在互不相關(guān)的獨(dú)立節(jié)點(diǎn)中,在節(jié)點(diǎn)中通過指針指向其前一個(gè)元素和后一個(gè)元素。 list 與 forward_list 非常相似:最主要的不

    2024年02月11日
    瀏覽(24)
  • stl中的list模擬實(shí)現(xiàn)

    stl中的list模擬實(shí)現(xiàn)

    首先我們要清楚list是一個(gè)帶頭雙向循環(huán)的鏈表。 在下面代碼中我們用到了 模板 ,并且用的是 struct 沒有用 class ,這是因?yàn)槲覀兪褂胹truct時(shí)相當(dāng)于 這一個(gè)類是公開的 ,當(dāng)然我們也可以使用class但是得使用友元函數(shù)比較麻煩。 我們可以查看stl的源碼進(jìn)行查看,如下: 我們可以

    2024年02月02日
    瀏覽(34)
  • 【C++入門到精通】C++入門 —— deque(STL)

    【C++入門到精通】C++入門 —— deque(STL)

    文章綁定了VS平臺下std::deque的源碼,大家可以下載了解一下?? 前面我們講了C語言的基礎(chǔ)知識,也了解了一些數(shù)據(jù)結(jié)構(gòu),并且講了有關(guān)C++的命名空間的一些知識點(diǎn)以及關(guān)于C++的缺省參數(shù)、函數(shù)重載,引用 和 內(nèi)聯(lián)函數(shù)也認(rèn)識了什么是類和對象以及怎么去new一個(gè) ‘對象’ ,以及

    2024年02月12日
    瀏覽(23)
  • 【C++入門到精通】C++入門 —— vector (STL)

    【C++入門到精通】C++入門 —— vector (STL)

    前面我們講了C語言的基礎(chǔ)知識,也了解了一些數(shù)據(jù)結(jié)構(gòu),并且講了有關(guān)C++的命名空間的一些知識點(diǎn)以及關(guān)于C++的缺省參數(shù)、函數(shù)重載,引用 和 內(nèi)聯(lián)函數(shù)也認(rèn)識了什么是類和對象以及怎么去new一個(gè) ‘對象’ ,也相信大家都掌握的不錯(cuò),接下來博主將會(huì)帶領(lǐng)大家繼續(xù)學(xué)習(xí)有關(guān)

    2024年02月13日
    瀏覽(26)
  • C++ STL->list模擬實(shí)現(xiàn)

    C++ STL->list模擬實(shí)現(xiàn)

    list list文檔 list是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。 list的底層是雙向鏈表結(jié)構(gòu),雙向鏈表中每個(gè)元素存儲(chǔ)在互不相關(guān)的獨(dú)立節(jié)點(diǎn)中,在節(jié)點(diǎn)中通過指針指向 其前一個(gè)元素和后一個(gè)元素。 list與forward_list非常相似:最主

    2024年02月20日
    瀏覽(25)
  • <C++> STL_list

    <C++> STL_list

    list是可以在常數(shù)范圍內(nèi)在任意位置進(jìn)行插入和刪除的序列式容器,并且該容器可以前后雙向迭代。 list的底層是雙向鏈表結(jié)構(gòu),雙向鏈表中每個(gè)元素存儲(chǔ)在互不相關(guān)的獨(dú)立節(jié)點(diǎn)中,在節(jié)點(diǎn)中通過指針指向 其前一個(gè)元素和后一個(gè)元素。 list與forward_list非常相似:最主要的不同在

    2024年02月10日
    瀏覽(24)

覺得文章有用就打賞一下文章作者

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

請作者喝杯咖啡吧~博客贊助

支付寶掃一掃領(lǐng)取紅包,優(yōu)惠每天領(lǐng)

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包