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

【C++】手撕 list類(包含迭代器)

這篇具有很好參考價值的文章主要介紹了【C++】手撕 list類(包含迭代器)。希望對大家有所幫助。如果存在錯誤或未考慮完全的地方,請大家不吝賜教,您也可以點擊"舉報違法"按鈕提交疑問。

目錄

1,list的介紹及使用

2,list_node

3,list_node()

3,list

4,list()

5,push_back(const T& x)

6,print()

7,_list_iterator

8,operator*()

9,begin()

10,end()

11,operator->()

12,operator++()

13,operator++(int)

14,operator--()

15,operator--(int)

16,operator==(const sefl& s)

17,operator!=(const sefl& s)

18,_list_const_iterator

19,list(iterator first, iterator last)

20,begin()const

21,end()const

22,list(const list& lt)

23,operator=(list lt)

24,insert(iterator pos, const T& x)

25,erase(iterator pos)

26,clear()

27,~list()

28,push_front(const T& x)

29,pop_front()

30,pop_back()

31,源代碼

32,總結(jié)


【C++】手撕 list類(包含迭代器),C++,c++,開發(fā)語言,算法,list,數(shù)據(jù)結(jié)構(gòu)

1,list的介紹及使用

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

2,list 的底層是雙向鏈表結(jié)構(gòu),雙向鏈表中每個元素存儲在互不相關(guān)的獨立節(jié)點中,在節(jié)點中通過指針指向其前一個元素和后一個元素。

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

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

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

2,list_node

結(jié)點的結(jié)構(gòu)體框架

template<class T>
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T data;
	};

因為是雙向循環(huán)鏈表,需要一個上指針 _prev,下指針 _next,還有數(shù)據(jù) data;

3,list_node()

對結(jié)點進行初始化

		list_node(const T& x = T())
			:_next(nullptr)
			, _prev(nullptr)
			, data(x)
		{}

然后還要將其初始化,指針為空,數(shù)據(jù)為內(nèi)置類型初始化的值;

3,list

鏈表結(jié)構(gòu)框架

	template <class T>
	class list
	{
		typedef list_node<T> node;
	public:

	private:
		node* _head;
	};

鏈表是帶頭結(jié)點的,所以我們需要一個哨兵位頭結(jié)點;

4,list()

對鏈表初始化

		void empty_init()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}

		list()
		{
			empty_init();
		}

因為我們是雙向循環(huán)鏈表,所以我們的下一個結(jié)點和上一個結(jié)點都是指向自己的,形成一個環(huán);

5,push_back(const T& x)

尾插

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

我們先找到尾結(jié)點(tail),申請一個新結(jié)點,然后就插入其中;

6,print()

打印數(shù)據(jù)

		void print()
		{
			node* cur = _head->_next;
			while (cur != _head)
			{
				cout << cur->data << " ";
				cur = cur->_next;
			}
		}

哨兵位頭結(jié)點本身是沒有數(shù)據(jù)的,所以要從下一個結(jié)點開始

	void test1()
	{
		wxd::list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		lt1.print();
	}

【C++】手撕 list類(包含迭代器),C++,c++,開發(fā)語言,算法,list,數(shù)據(jù)結(jié)構(gòu)

也是沒有任何問題的

7,_list_iterator

迭代器的框架和初始化


	template<class T,class ref,class ptr>
	struct _list_iterator
	{
		typedef list_node<T> node;
		typedef _list_iterator<T,ref,ptr> sefl;
		node* _node;

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

有人會好奇,為什么模板里面有三個參數(shù),現(xiàn)在先不急下面會進行分曉的;

指向結(jié)點的迭代器嘛,底層類型就是指針;

初始化也是一樣,傳來什么就是什么;

8,operator*()

迭代器解引用取值

		ref operator*()
		{
			return _node->data;
		}

ref 其實就是 T&;

9,begin()

找頭結(jié)點

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

直接返回構(gòu)造完后的結(jié)果;

10,end()

最后一個結(jié)點的下一個位置

		iterator end()
		{
			return iterator(_head);
		}

然后我們就可以試一下迭代器打印了;

	void print_list(const list<int>& lt)
	{
		list<int>::const_iterator it = lt.begin();
		while (it != lt.end())
		{
			cout << *it << " ";
			++it;
		}
		cout << endl;
	}

	void test1()
	{
		wxd::list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		print_list(lt1);
	}

【C++】手撕 list類(包含迭代器),C++,c++,開發(fā)語言,算法,list,數(shù)據(jù)結(jié)構(gòu)

11,operator->()

迭代器箭頭指向取值

		ptr operator->()
		{
			return &_node->data;
		}

返回的是 data 的地址,ptr 是 T* ;

12,operator++()

迭代器前置++

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

sefl 是??_list_iterator<T,ref,ptr>;

13,operator++(int)

迭代器后置++

		sefl operator++(int)
		{
			sefl tmp(*this);
			_node = _node->_next;
			return tmp;
		}

返回的是之前的值,但其實已經(jīng)改變了;

14,operator--()

迭代器前置 - -

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

15,operator--(int)

迭代器后置 - -

		sefl operator--(int)
		{
			sefl tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

16,operator==(const sefl& s)

迭代器判斷相等

		bool  operator==(const sefl& s)
		{
			return _node == s._node;
		}

判斷迭代器是否相等比較 _node 就可以了;

17,operator!=(const sefl& s)

判斷是否不相等

		bool operator!=(const sefl& s)
		{
			return _node != s._node;
		}

18,_list_const_iterator

然后這個是 const 迭代器版本的,這里我就不一個一個寫了;

template<class T>
	struct _list_const_iterator
	{
		typedef list_node<T> node;
		typedef _list_const_iterator<T> sefl;
		node* _node;

		_list_const_iterator(node* n)
			:_node(n)
		{}

		const T& operator*()
		{
			return _node->data;
		}

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

		sefl operator++(int)
		{
			sefl tmp(*this);
			_node = _node->_next;
			return tmp;
		}

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

		sefl operator--(int)
		{
			sefl tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool  operator==(const sefl& s)
		{
			return _node == s._node;
		}

		bool operator!=(const sefl& s)
		{
			return _node != s._node;
		}

	};

其實吧,_list_const_iterator 跟?_list_iterator 就是內(nèi)部函數(shù)參數(shù)的返回值不同罷了,我們可以用模板參數(shù)來實例化,這樣就不用寫兩個迭代器了;

template <class 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;

list 下面這樣操作就可以了,普通迭代器模板一個版本,const 迭代器模板內(nèi)的參數(shù)加上const就可以了,等調(diào)用的時候編譯器會自動匹配的;

19,list(iterator first, iterator last)

迭代器區(qū)間構(gòu)造

		template<class iterator>
		list(iterator first, iterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

20,begin()const

const 版本取頭結(jié)點

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

21,end()const

const 版本取尾結(jié)點的下一個位置

		const_iterator end()const
		{
			return const_iterator(_head);
		}

22,list(const list<T>& lt)

拷貝構(gòu)造

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

		list(const list<T>& lt)
		{
			empty_init();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}

先把要拷貝的區(qū)間信息構(gòu)造另一個 list ,然后再與 this 指針的 _head哨兵位頭結(jié)點進行交換即可;

23,operator=(list<T> lt)

賦值

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

24,insert(iterator pos, const T& x)

插入

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

定義前一個結(jié)點,和本身的結(jié)點,然后再進行插入即可;

	void test3()
	{
		wxd::list<int> lt1;
		lt1.push_back(1);
		lt1.push_back(2);
		lt1.push_back(3);
		lt1.push_back(4);

		auto pos = find(lt1.begin(), lt1.end(), 3);
		lt1.insert(pos, 9);
		print_list(lt1);
	}

【C++】手撕 list類(包含迭代器),C++,c++,開發(fā)語言,算法,list,數(shù)據(jù)結(jié)構(gòu)

25,erase(iterator pos)

擦除

		iterator erase(iterator pos)
		{
			assert(pos != end());

			node* next = pos._node->_next;
			node* tail = pos._node->_prev;

			tail->_next = next;
			next->_prev = tail;

			delete pos._node;
			return iterator(next);
		}

先斷言一下,哨兵位結(jié)點是不能擦除的;

然后找到前一個結(jié)點,后一個結(jié)點,在進行互相綁定;

在釋放要刪除的空間;

26,clear()

清除

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

27,~list()

析構(gòu)函數(shù)

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

先清空結(jié)點,然后再是否哨兵位頭結(jié)點置空即可;

28,push_front(const T& x)

頭插

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

直接用 insert 插入更加方便;

29,pop_front()

頭刪

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

30,pop_back()

尾刪

		void pop_back()
		{
			erase(_head->_prev);
		}

31,源代碼

#define _CRT_SECURE_NO_WARNINGS 1
#include<iostream>
#include<assert.h>
using namespace std;
	template<class T>
	struct list_node
	{
		list_node<T>* _next;
		list_node<T>* _prev;
		T data;

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

	template<class T,class ref,class ptr>
	struct _list_iterator
	{
		typedef list_node<T> node;
		typedef _list_iterator<T,ref,ptr> sefl;
		node* _node;

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

		ref operator*()
		{
			return _node->data;
		}

		ptr operator->()
		{
			return &_node->data;
		}

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

		sefl operator++(int)
		{
			sefl tmp(*this);
			_node = _node->_next;
			return tmp;
		}

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

		sefl operator--(int)
		{
			sefl tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

		bool  operator==(const sefl& s)
		{
			return _node == s._node;
		}

		bool operator!=(const sefl& s)
		{
			return _node != s._node;
		}

	};

	template <class 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;

		void empty_init()
		{
			_head = new node;
			_head->_next = _head;
			_head->_prev = _head;
		}

		list()
		{
			empty_init();
		}

		template<class iterator>
		list(iterator first, iterator last)
		{
			empty_init();
			while (first != last)
			{
				push_back(*first);
				++first;
			}
		}

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

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

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

		iterator end()
		{
			return iterator(_head);
		}

		const_iterator end()const
		{
			return const_iterator(_head);
		}

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

		list(const list<T>& lt)
		{
			empty_init();
			list<T> tmp(lt.begin(), lt.end());
			swap(tmp);
		}

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


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

		iterator erase(iterator pos)
		{
			assert(pos != end());

			node* next = pos._node->_next;
			node* tail = pos._node->_prev;

			tail->_next = next;
			next->_prev = tail;

			delete pos._node;
			return iterator(next);
		}

		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

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

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

		void pop_back()
		{
			erase(_head->_prev);
		}

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

		void print()
		{
			node* cur = _head->_next;
			while (cur != _head)
			{
				cout << cur->data << " ";
				cur = cur->_next;
			}
		}


	private:
		node* _head;
	};

32,總結(jié)

我們就先搞一個大概的,其中還有很多分支,比如我們寫的是擦除某個數(shù)據(jù),其實也可以擦除某個范圍,這些就靠大家去摸索,查閱文檔了;

list 類的實現(xiàn)就到這里了;

加油!

【C++】手撕 list類(包含迭代器),C++,c++,開發(fā)語言,算法,list,數(shù)據(jù)結(jié)構(gòu)文章來源地址http://www.zghlxwxcb.cn/news/detail-785361.html

到了這里,關(guān)于【C++】手撕 list類(包含迭代器)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關(guān)文章,希望大家以后多多支持TOY模板網(wǎng)!

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

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

相關(guān)文章

  • C++初階:適合新手的手撕list(模擬實現(xiàn)list)

    C++初階:適合新手的手撕list(模擬實現(xiàn)list)

    上次講了常用的接口:今天就來進行模擬實現(xiàn)啦 list.h頭文件:包含類的全部(函數(shù)的聲明與定義) reverseIterator.h文件:進行反向迭代器的實現(xiàn) test.cpp源文件:進行調(diào)用test函數(shù),測試和完善功能 基本結(jié)構(gòu): ListNode 結(jié)構(gòu)體: 定義了鏈表的節(jié)點結(jié)構(gòu),包含了三個成員變量:前驅(qū)指針

    2024年02月20日
    瀏覽(29)
  • Java02-迭代器,數(shù)據(jù)結(jié)構(gòu),List,Set ,Map,Collections工具類

    Java02-迭代器,數(shù)據(jù)結(jié)構(gòu),List,Set ,Map,Collections工具類

    目錄 什么是遍歷? 一、Collection集合的遍歷方式 1.迭代器遍歷 方法 流程 案例 2. foreach(增強for循環(huán))遍歷 案例 3.Lamdba表達式遍歷 案例 二、數(shù)據(jù)結(jié)構(gòu) 數(shù)據(jù)結(jié)構(gòu)介紹 常見數(shù)據(jù)結(jié)構(gòu) 棧(Stack) 隊列(Queue) 鏈表(Link) 散列表(Hash Table) 樹(Tree) List接口 ArraysList集合 Linked

    2024年02月14日
    瀏覽(54)
  • 【c++】list迭代器失效問題

    【c++】list迭代器失效問題

    目錄 一、list iterator的使用 二、list的迭代器失效 ? ? ? ? 對于list的迭代器的用法,可以將它看做一個指針(實際要更加復(fù)雜)來使用,該指針指向list中的一個節(jié)點。 ? ? ? ? 【注意】 ? ? ? ? (1)begin和end為正向迭代器,對迭代器執(zhí)行++操作,迭代器向后移動 ? ? ? ? (2)r

    2024年01月23日
    瀏覽(23)
  • Java02-迭代器,數(shù)據(jù)結(jié)構(gòu),List,Set ,TreeSet集合,Collections工具類

    Java02-迭代器,數(shù)據(jù)結(jié)構(gòu),List,Set ,TreeSet集合,Collections工具類

    目錄 什么是遍歷? 一、Collection集合的遍歷方式 1.迭代器遍歷 方法 流程 案例 2. foreach(增強for循環(huán))遍歷 案例 3.Lamdba表達式遍歷 案例 二、數(shù)據(jù)結(jié)構(gòu) 數(shù)據(jù)結(jié)構(gòu)介紹 常見數(shù)據(jù)結(jié)構(gòu) 棧(Stack) 隊列(Queue) 鏈表(Link) 散列表(Hash Table) 樹(Tree) List接口 ArraysList集合 Linked

    2024年02月14日
    瀏覽(54)
  • 初識Go語言25-數(shù)據(jù)結(jié)構(gòu)與算法【堆、Trie樹、用go中的list與map實現(xiàn)LRU算法、用go語言中的map和堆實現(xiàn)超時緩存】

    初識Go語言25-數(shù)據(jù)結(jié)構(gòu)與算法【堆、Trie樹、用go中的list與map實現(xiàn)LRU算法、用go語言中的map和堆實現(xiàn)超時緩存】

    ??堆是一棵二叉樹。大根堆即任意節(jié)點的值都大于等于其子節(jié)點。反之為小根堆。 ??用數(shù)組來表示堆,下標為 i 的結(jié)點的父結(jié)點下標為(i-1)/2,其左右子結(jié)點分別為 (2i + 1)、(2i + 2)。 構(gòu)建堆 ??每當有元素調(diào)整下來時,要對以它為父節(jié)點的三角形區(qū)域進行調(diào)整。 插入元素

    2024年02月12日
    瀏覽(93)
  • 【C++進階(四)】STL大法--list深度剖析&list迭代器問題探討

    【C++進階(四)】STL大法--list深度剖析&list迭代器問題探討

    ??博主CSDN主頁:杭電碼農(nóng)-NEO?? ? ?專欄分類:C++從入門到精通? ? ??代碼倉庫:NEO的學習日記?? ? ??關(guān)注我??帶你學習C++ ? ???? 本質(zhì)重點: 本章重點講解list的接口函數(shù)的熟悉 并且講解list迭代器失效的特性 最后講解迭代器的功能分類以及 算法庫函數(shù)中誰能用誰不能

    2024年02月09日
    瀏覽(55)
  • 數(shù)據(jù)結(jié)構(gòu)與算法之手撕排序算法

    數(shù)據(jù)結(jié)構(gòu)與算法之手撕排序算法

    為什么要學習排序算法? 根據(jù)統(tǒng)計,早起大型機CPU資源的四分之一都花在了數(shù)據(jù)排序上面。排序算法作為最基礎(chǔ)的算法,各種操作系統(tǒng)、編程語言都提供了內(nèi)置的實現(xiàn)。既然排序?qū)崿F(xiàn)隨處可見,我們?yōu)槭裁催€要自己動手實現(xiàn)呢?雖然經(jīng)典算法要動手寫寫加深印象的道理都懂,

    2023年04月16日
    瀏覽(22)
  • 包含了父子關(guān)系的單位對象的List數(shù)據(jù)轉(zhuǎn)成樹狀結(jié)構(gòu)

    你知道的越多,你不知道的越多 點贊再看,養(yǎng)成習慣 如果您有疑問或者見解,或者沒有積分想獲取項目和定制項目,歡迎指教: 企鵝:869192208 需求 將一個包含了父子關(guān)系的單位對象的 List 數(shù)據(jù),轉(zhuǎn)成一個帶層級關(guān)系的數(shù)據(jù)。 原始數(shù)據(jù),用 json 格式展示 實現(xiàn)代碼: 最終返

    2024年02月12日
    瀏覽(13)
  • 數(shù)據(jù)結(jié)構(gòu)之隊列詳解(C語言手撕)

    數(shù)據(jù)結(jié)構(gòu)之隊列詳解(C語言手撕)

    ??個人名片: ??作者簡介:一名樂于分享在學習道路上收獲的大二在校生 ??個人主頁??:GOTXX ??個人WeChat:ILXOXVJE ??本文由GOTXX原創(chuàng),首發(fā)CSDN?????? ??系列專欄:零基礎(chǔ)學習C語言----- 數(shù)據(jù)結(jié)構(gòu)的學習之路----C++的學習之路 ??每日一句:如果沒有特別幸運,那就請?zhí)?/p>

    2024年03月10日
    瀏覽(30)
  • C++:模擬實現(xiàn)list及迭代器類模板優(yōu)化方法

    C++:模擬實現(xiàn)list及迭代器類模板優(yōu)化方法

    本篇模擬實現(xiàn)簡單的list和一些其他注意的點 如下所示是利用拷貝構(gòu)造將一個鏈表中的數(shù)據(jù)挪動到另外一個鏈表中,構(gòu)造兩個相同的鏈表 lt作為形參,傳引用可以提高傳參的效率,同時應(yīng)該加上const修飾來保證不會因為不小心修改了形參導(dǎo)致外部的實參也被修改,這樣的結(jié)果是

    2024年02月13日
    瀏覽(21)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領(lǐng)取紅包

二維碼2

領(lǐng)紅包