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

C++ list模擬實現(xiàn)

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

list模擬實現(xiàn)代碼:

namespace djx
{
	template<class T>
	struct list_node
	{
		T _data;
		list_node<T>* _prev;
		list_node<T>* _next;

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

	template<class T,class Ref,class 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->_data;
		}

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

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

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

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

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

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

		bool operator==(const self& 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;
		
		iterator begin()
		{
			return _head->_next;
		}

		iterator end()
		{
			return _head;
		}

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

		const_iterator end()const
		{
			return _head;
		}

		void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;
		}

		list()
		{
			empty_init();
		}

		list(const list<T>& lt)
		{
			empty_init();
			for (auto e : lt)
			{
				push_back(e);
			}
		}

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

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

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

		void push_back(const T& x)
		{
			insert(end(), x);
		}

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

		void pop_back()
		{
			erase(--end());
		}

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

		iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;
			Node* newnode = new Node(x);
			Node* prev = cur->_prev;

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

			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
			return newnode;
		}

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

			delete cur;
			prev->_next = next;
			next->_prev = prev;
			_size--;
			return next;
		}
		
		size_t size()
		{
			return _size;
		}

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

源碼中的list實現(xiàn)為帶頭雙向鏈表

C++ list模擬實現(xiàn),C++,c++,list

?文章來源地址http://www.zghlxwxcb.cn/news/detail-679593.html

list類的對象有兩個成員:指向頭結(jié)點的指針_head,統(tǒng)計數(shù)據(jù)個數(shù)的_size

在模擬實現(xiàn)list之前,需要先模擬實現(xiàn)結(jié)點類,迭代器類

結(jié)點類:三個成員,_data _prev _next,實現(xiàn)成struct(也是類,不過與class不同的是,它的成員都是公開的,都可以在類外訪問),因為這三個成員,在迭代器類中都要使用訪問,設it是迭代器,*it就會返回結(jié)點中值(_data)的引用,it++(要訪問結(jié)點中的_next) , it--(要訪問結(jié)點中的_prev)

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

		list_node(const T& x = T())//x是匿名對象的引用,const延長了匿名對象的生命周期,x銷毀,匿名對象才銷毀,匿名對象會調(diào)用它的構(gòu)造函數(shù),完成初始化
			:_data(x)
			,_prev(nullptr)
			,_next(nullptr)
		{}
	};

要寫構(gòu)造函數(shù):list類中的push_back插入數(shù)據(jù)時,需要new一個結(jié)點,并傳數(shù)值

? ? ? ? ? ? ? ? ? ? ? ? ?調(diào)用構(gòu)造函數(shù)時,若是直接使用編譯器生成的默認構(gòu)造函數(shù),則無法傳參

構(gòu)造函數(shù)的參數(shù)設計成缺省參數(shù):有傳實參過來就使用此值,沒有傳參過來就用匿名對象去拷貝構(gòu)造_data,使用匿名對象去拷貝構(gòu)造_data的情形:list類中的無參構(gòu)造函數(shù)-->讓list中的成員變量_head指向一個new出來的頭結(jié)點,頭結(jié)點中不存儲任何有效數(shù)據(jù),故而new時無需傳參

迭代器類:一個成員 _node(結(jié)點的指針)

設計成struct:在list類中設計insert和erase時,傳參給它們的是iterator迭代器,我們要使用迭代器中的成員變量(結(jié)點的指針)即要訪問迭代器中的成員,那么設計成struct會比設計成class類方便不少

list的迭代器與vector,string類不同,在模擬實現(xiàn)vector和string的迭代器時,它們可以用原生指針來實現(xiàn),因為完美契合原生指針的行為,但是模擬實現(xiàn)list的迭代器時,它必須設計成一個類,是對原生指針的封裝,原因:

若是list的迭代器就用原生指針來實現(xiàn),那么*it(it是一個迭代器)得到的不是數(shù)據(jù),而是結(jié)點

it++ 不能走向下一個數(shù)據(jù),故而需要對原生指針進行封裝,讓*it得到數(shù)據(jù),it++,走向下一個數(shù)據(jù)

template<class T,class Ref,class Ptr>
	struct __list_iterator
	{
		typedef list_node<T> Node;
		typedef __list_iterator<T, Ref, Ptr> self;

		Node* _node;

		__list_iterator(Node* node)//要寫帶參的構(gòu)造,因為在list類中實現(xiàn)begin()時,返回值的類型是迭代器,但是我們返回的可以是結(jié)點的指針,單參數(shù)的構(gòu)造函數(shù)支持隱式類型轉(zhuǎn)換,也可以是迭代器,但是此迭代器中的成員變量(結(jié)點的指針)需要和第一個結(jié)點的指針一樣
			:_node(node)
		{}

		Ref operator*()//Ref可以是T&(普通迭代器) const T& (const迭代器)
		{
			return _node->_data;
		}

		Ptr operator->()Ptr可以是T* (普通迭代器) const T* (const迭代器)
		{
			return &_node->_data;
		}

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

		self operator++(int)//后置++
		{
			self tmp(*this);
			_node = _node->_next;
			return tmp;//返回迭代器++之前的值
		}

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

		self operator--(int)//后置--
		{
			self tmp(*this);
			_node = _node->_prev;
			return tmp;
		}

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

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

迭代器有非const對象調(diào)用的,也有const對象調(diào)用的,二者的區(qū)別僅僅是能否修改的問題,*迭代器返回的是數(shù)據(jù)的引用,const對象調(diào)用的迭代器返回的也是數(shù)據(jù)的引用,但是const修飾的

迭代器-> 返回的是數(shù)據(jù)的地址,const對象調(diào)用的迭代器返回的是const修飾的數(shù)據(jù)地址

(迭代器可以看作是模擬原生指針的行為,若是數(shù)據(jù)為自定義類型,那么迭代器->就可以訪問到自定義類型對象中的成員,實際上看成是原生指針的迭代器->?無法做到,但是對原生指針封裝而出現(xiàn)的迭代器可以做到,只要迭代器->返回的是數(shù)據(jù)的指針,那么有了自定義類型對象指針,不就可以訪問它里面的成員了嗎)

綜上來看,我們只需要寫一份迭代器類的模板,根據(jù)實例化參數(shù)的不同,生成不同的迭代器

迭代器需要三個模板參數(shù):T(迭代器類中的成員變量是結(jié)點的指針,結(jié)點實例化需要)

模板參數(shù) Ref? : 迭代器類中重載*運算符所用,重載*運算符的函數(shù)要返回數(shù)據(jù)的引用,而若是const對象的迭代器解引用,就要用const去修飾返回值

模板參數(shù)Ptr :迭代器類中重載->運算符所用,重載->運算符的函數(shù)返回數(shù)據(jù)的指針,而若是const對象的迭代器->,也要用const去修飾返回值

那么在list類中,設計普通迭代器,const對象調(diào)用的迭代器時,就可以用迭代器類的模板,實例化參數(shù)不同就會是完全不同的類型,普通迭代器用迭代器類的模板實例化,傳參 T? ?T&? ?T*

const對象調(diào)用的迭代器用迭代器類的模板實例化,傳參 T? const T&? ?const T*

構(gòu)造函數(shù):

1 無參的構(gòu)造

? ? 讓list對象中的成員變量_head指向一個頭指針(雙向循環(huán))

? ? 參照源碼list的實現(xiàn):

C++ list模擬實現(xiàn),C++,c++,list

?

        void empty_init()
		{
			_head = new Node;
			_head->_next = _head;
			_head->_prev = _head;
			_size = 0;
		}

		list()
		{
			empty_init();
		}

2 拷貝構(gòu)造(深拷貝)

        list(const list<T>& lt)
		{
			empty_init();
			for (auto e : lt)
			{
				push_back(e);
			}
		}

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

        ~list()
		{
			clear();
			delete _head;//釋放頭結(jié)點
			_head = nullptr;
		}

		void clear()//清除數(shù)據(jù)
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it);
			}
		}

賦值重載:

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

		list<T>& operator=(list<T> lt)///lt是實參的深拷貝,lt銷毀會釋放掉原本由*this申請的空間
		{
			swap(lt);//交換*this和lt
			return *this;
		}

迭代器:

        typedef __list_iterator<T, T&, T*> iterator;
		typedef __list_iterator<T, const T&, const T*> const_iterator;
		
		iterator begin()
		{
			return _head->_next;
		}

		iterator end()
		{
			return _head;
		}

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

		const_iterator end()const
		{
			return _head;
		}

測試1:

void test1()
{
	djx::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	djx::list<int>:: iterator it = lt.begin();
	while (it != lt.end())
	{
		*it += 20;
		cout << *it << " ";
		it++;
	}
	cout << endl;

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}

C++ list模擬實現(xiàn),C++,c++,list

測試2:

void test2()
{
	djx::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	djx::list<int> lt1(lt);//拷貝構(gòu)造

	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	for (auto e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	djx::list<int> lt2;
	lt2.push_back(100);
	lt2.push_back(200);
	lt2.push_back(300);
	lt2.push_back(400);
	lt2.push_back(500);

	lt1 = lt2;//賦值重載

	for (auto e : lt1)
	{
		cout << e << " ";
	}
	cout << endl;

	for (auto e : lt2)
	{
		cout << e << " ";
	}
	cout << endl;

}

C++ list模擬實現(xiàn),C++,c++,list?

?

插入:

?1 push_back

        void push_back(const T& x)
		{
			insert(end(), x);
		}

2 push_front

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

3 insert

        iterator insert(iterator pos, const T& x)
		{
			Node* cur = pos._node;//當前節(jié)點的指針
			Node* newnode = new Node(x);
			Node* prev = cur->_prev;

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

			newnode->_next = cur;
			cur->_prev = newnode;
			_size++;
			return newnode;//單參數(shù)的構(gòu)造函數(shù)支持隱式類型轉(zhuǎn)換
                           //或者寫成:iterator(newnode)
		}

刪除:

1 pop_back

        void pop_back()
		{
			erase(--end());
		}

2 pop_front

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

3 erase

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

			delete cur;
			prev->_next = next;
			next->_prev = prev;
			_size--;
			return next;//返回下一個數(shù)據(jù)的地址
		}

測試3:

struct AA
{
	AA(int a1 = 0, int a2 = 0)
		:_a1(a1)
		, _a2(a2)
	{}

	int _a1;
	int _a2;
};

void test3()
{
	djx::list<AA> lt;
	lt.push_back(AA(1, 1));
	lt.push_back(AA(2, 2));
	lt.push_back(AA(3, 3));

	djx::list<AA>::iterator it = lt.begin();
	while (it != lt.end())
	{
		//cout << (*it)._a1 << " "<<(*it)._a2<<endl;
		cout << it->_a1 << " " << it->_a2 << endl;
		it++;
	}
	cout << endl;
}

C++ list模擬實現(xiàn),C++,c++,list

題外:

?設計一個打印函數(shù),打印任意list對象

template<typename T>//不可以用class
void print_list(const djx:: list<T>& lt)
{
    //list<T>未實例化的類模板,編譯器不能去它里面去找
    //編譯器就無法list<T>::const_iterator是內(nèi)嵌類型,還是靜態(tài)成員變量
    //前面加一個typename就是告訴編譯器,這里是一個類型,等list<T>實例化,再去類里面找
	typename djx::list<T>::const_iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

打印任意容器

template<typename Container>
void print_container(const Container& con)
{
	typename Container::const_iterator it = con.begin();
	while (it != con.end())
	{
		cout << *it << " ";
		it++;
	}
	cout << endl;
}

測試4:

void test4()
{
	djx::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	print_list(lt);
}

C++ list模擬實現(xiàn),C++,c++,list

測試5:

void test5()
{
	djx::list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	print_container(lt);

	djx::list<string> lt1;
	lt1.push_back("1111111111111");
	lt1.push_back("1111111111111");
	lt1.push_back("1111111111111");
	lt1.push_back("1111111111111");
	lt1.push_back("1111111111111");
	//print_list(lt1);
	print_container(lt1);

	vector<string> v;
	v.push_back("222222222222222222222");
	v.push_back("222222222222222222222");
	v.push_back("222222222222222222222");
	v.push_back("222222222222222222222");
	print_container(v);

}

?C++ list模擬實現(xiàn),C++,c++,list

?

到了這里,關于C++ list模擬實現(xiàn)的文章就介紹完了。如果您還想了解更多內(nèi)容,請在右上角搜索TOY模板網(wǎng)以前的文章或繼續(xù)瀏覽下面的相關文章,希望大家以后多多支持TOY模板網(wǎng)!

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

領支付寶紅包贊助服務器費用

相關文章

  • 《C++ list的模擬實現(xiàn)》

    《C++ list的模擬實現(xiàn)》

    本文主要介紹list容器的模擬實現(xiàn) list示意圖: 首先需要定義一個節(jié)點 的結(jié)構(gòu)體 我們之前所理解的是:迭代器理解為像指針一樣的東西,但是在list中有些不同 我們可以來觀察一下STL源碼中大佬是怎么封裝的: 我們可以看到,只有一個成員,那就是一個結(jié)點的指針node,link_

    2024年02月07日
    瀏覽(21)
  • [C++]:12:模擬實現(xiàn)list

    [C++]:12:模擬實現(xiàn)list

    1.節(jié)點結(jié)構(gòu): 1.SGI下的節(jié)點通過兩個結(jié)構(gòu)體實現(xiàn)。 2.基礎的鏈表節(jié)點只包括前驅(qū)指針和后繼指針。 3.鏈表節(jié)點去繼承基礎鏈表節(jié)點,新增節(jié)點數(shù)據(jù)。 4.優(yōu)化掉指針類型帶模板參數(shù)。 2.節(jié)點構(gòu)造函數(shù): 1.節(jié)點本身在這個地方是沒有構(gòu)造函數(shù)的。 2.觀察下面的鏈表的結(jié)構(gòu)和鏈表的

    2024年01月22日
    瀏覽(23)
  • 【C++】list的模擬實現(xiàn)

    【C++】list的模擬實現(xiàn)

    list為任意位置插入刪除的容器,底層為帶頭雙向循環(huán)鏈表 begin() 代表第一個結(jié)點,end()代表最后一個結(jié)點的下一個 1. list_node 類設計 C++中,Listnode作為類名,而next和prev都是類指針,指針引用成員時使用-,而對象引用成員時使用 . 通過顯示實例化,將兩個類指針指定類型為T

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

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

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

    2024年02月20日
    瀏覽(25)
  • 【C++學習手札】模擬實現(xiàn)list

    【C++學習手札】模擬實現(xiàn)list

    ? ?? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ??????????????? ?? 慕斯主頁 : 修仙—別有洞天 ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?????????????????? ?? 今日夜電波 : リナリア—まるりとりゅうが ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ? ?

    2024年02月05日
    瀏覽(92)
  • C++:list使用以及模擬實現(xiàn)

    C++:list使用以及模擬實現(xiàn)

    list是一個類模板,加類型實例化才是具體的類 。 list是可以 在任意位置進行插入和刪除 的序列式容器。 list的 底層是雙向循環(huán)鏈表結(jié)構(gòu) ,鏈表中每個元素存儲在互不相關的獨立節(jié)點中,在節(jié)點中通過指針指向其前一個元素和后一個元素。 與其他序列式容器相比, list最大的

    2024年02月11日
    瀏覽(22)
  • C++ list鏈表模擬實現(xiàn)

    C++ list鏈表模擬實現(xiàn)

    目錄 前言: 模擬實現(xiàn): 迭代器的實現(xiàn): list類功能函數(shù)實現(xiàn): ?初始化成空函數(shù)(empty_init): 構(gòu)造函數(shù): ?拷貝構(gòu)造函數(shù): 尾插(push_back): 插入(insert): 刪除(erase): ?尾刪(pop_back): 頭插(push_front): 頭刪(pop_front): ?清理(clear): ?交換(swap): 賦值重載:

    2024年04月12日
    瀏覽(46)
  • 【C++修煉之路】list 模擬實現(xiàn)

    【C++修煉之路】list 模擬實現(xiàn)

    ??作者主頁:@安 度 因 ??學習社區(qū):StackFrame ??專欄鏈接:C++修煉之路

    2024年02月16日
    瀏覽(15)
  • C++——list類及其模擬實現(xiàn)

    C++——list類及其模擬實現(xiàn)

    前言:這篇文章我們繼續(xù)進行C++容器類的分享—— list , 也就是數(shù)據(jù)結(jié)構(gòu)中的鏈表 ,而且是 帶頭雙向循環(huán)鏈表 。 由于要滿足存儲任意類型的數(shù)據(jù),所以我們必須要使用模版來進行定義 。? 關于list類中的最難之處,就是 迭代器 了。 因為 迭代器的原理即為指針 ,對于 st

    2024年04月10日
    瀏覽(15)
  • 【C++】list容器功能模擬實現(xiàn)

    【C++】list容器功能模擬實現(xiàn)

    ? ? ? ? 上一次介紹了list隊容器的迭代器模擬,這次模擬實現(xiàn)list的簡單功能,尤其要注意 構(gòu)造函數(shù)、析構(gòu)函數(shù)、以及賦值運算符重載 的實現(xiàn)。 ? ? ? ? list容器需要接納所有類型的數(shù)據(jù),因此,結(jié)構(gòu)設置與迭代器設置同理,需要引入結(jié)點,數(shù)據(jù)。 ? ? //結(jié)點結(jié)構(gòu) ? ? templ

    2024年01月24日
    瀏覽(14)

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

支付寶掃一掃打賞

博客贊助

微信掃一掃打賞

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

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

二維碼1

領取紅包

二維碼2

領紅包