0
点赞
收藏
分享

微信扫一扫

Sass(Syntactically Awesome Stylesheets)是一种强大的CSS预处理器

                                                

🔥个人主页:北辰水墨

🔥专栏:C++学习仓

Alt

一、list的介绍:

列表
列表是一种序列容器,允许在序列的任何位置进行时间复杂度为O(1)的插入和删除操作,并可在前后两个方向上进行迭代

列表容器被实现为双向链表;双向链表可以将它们包含的每个元素存储在不同且不相关的存储位置中。通过将每个元素关联到其前面的元素和后面的元素的链接来在内部保持顺序。

它们与forward_list非常相似:主要区别在于forward_list对象是单向链表,因此forward_list对象只能向前迭代,作为交换,forward_list对象相对较小和更高效。

与其他基本标准序列容器(数组,向量和双端队列)相比,列表在已获得迭代器的情况下通常在容器内的任何位置执行插入、提取和移动元素方面表现更好,因此在那些大量使用这些操作的算法(如排序算法)中也表现更好。

与其他序列容器相比,列表和forward_list的主要缺点是它们缺乏通过位置直接访问元素的能力;例如,要访问列表中的第六个元素,需要从已知位置(如开头或结尾)迭代到该位置,这在这两者之间的距离上需要线性时间。它们还会消耗一些额外的内存来保存与每个元素关联的链接信息(对于大量小尺寸元素的大型列表可能是一个重要因素)。

二、接口函数:

2.1 构造函数:

 2.1.1 Default constructor (构造一个空的 std::list):
             std::list<int> myList1;    // 创建一个空的整型链表

2.1.2 Fill constructor (构造一个有特定数量元素且每个元素都有相同初始值的 std::list):
            std::list<int> myList2(5, 10); // 创建一个有5个元素的链表,每个元素都初始化为10

2.1.3 Range constructor (从另一个迭代器定义范围的容器中构建 std::list):
            std::vector<int> myVector{1, 2, 3, 4, 5};
            std::list<int> myList3(myVector.begin(), myVector.end()); // 使用vector的范围来初始化链表

2.1.4 Copy constructor (使用另一个 std::list 来构造一个新的 std::list, 是副本):
            std::list<int> myOriginalList{1, 2, 3, 4, 5};
            std::list<int> myList4(myOriginalList); // 使用另一个list来初始化这个新的list

2.2 迭代器

 用法保持不变:

#include<iostream>
#include<list>
using namespace std;
int main()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);
	list<int>::iterator it = lt.begin();
	while (it != lt.end())
	{
		cout << *it << " ";
		it++;
	}

	cout << endl;

	list<int>::reverse_iterator rit = lt.rbegin();
	while (rit != lt.rend())
	{
		cout << *rit << " ";
		rit++;
	}
	return 0;
}

2.3 容量操作: 

  • empty检测list是否为空,是返回true,否则返回false
  • size返回有效元素个数的值

2.4 元素访问:

  • front返回list的第一个节点值的引用
  • back返回list的最后一个节点值的引用

 2.5内容操作:

这里大多数函数我们在前面都讲解过,包括头插头删尾插尾删之类的。 

2.5.1 assign

清除原来的数据,再链接新数据(模拟实现原理,先clear(),再push_back() )

// list::assign
#include <iostream>
#include <list>

int main()
{
	std::list<int> first;
	std::list<int> second;

	first.assign(7, 100);                      // 7 ints with value 100

	second.assign(first.begin(), first.end()); // a copy of first

	int myints[] = { 1776,7,4 };
	first.assign(myints, myints + 3);            // assigning from array
	for (auto u : first)
	{
		std::cout << u << " ";
	}
	std::cout << std::endl;
	std::cout << "Size of first: " << int(first.size()) << '\n';
	std::cout << std::endl;
	for (auto u : second)
	{
		std::cout << u << " ";
	}
	std::cout << std::endl;
	std::cout << "Size of second: " << int(second.size()) << '\n';
	return 0;
}

2.5.2 

2.5.3  insert

      1. 不会出现迭代器失效:它不像vector那样会有异地扩容,挪动数据,iterator野指针的问题。

      2. 不用it接收返回值:那么it还是指向那个节点的地址。

      3. 用it接收返回值:就指向新添加的首节点的地址

#include <iostream>
#include <list>
#include <vector>

int main()
{
    std::list<int> mylist;
    std::list<int>::iterator it;

    // set some initial values:
    for (int i = 1; i <= 5; ++i) mylist.push_back(i); // 1 2 3 4 5

    it = mylist.begin();
    ++it;       // it points now to number 2           ^

    it=mylist.insert(it,3, 10);                       // 1 10 10 10 2 3 4 5
      用it接收返回值                                     ^
    mylist.insert(it, 2, 20);                      // 1 20 20 10 10 10 2 3 4 5
      没有用it接收返回值,还是指向那一块空间                  ^
    std::cout << "mylist contains:";
    for (it = mylist.begin(); it != mylist.end(); ++it)
        std::cout << ' ' << *it;
    std::cout << '\n';

    return 0;
}

2.5.4 erase

// erasing from list
#include <iostream>
#include <list>

int main ()
{
  std::list<int> mylist;
  std::list<int>::iterator it1,it2;

  // set some values:
  for (int i=1; i<10; ++i) mylist.push_back(i*10);

                              // 10 20 30 40 50 60 70 80 90
  it1 = it2 = mylist.begin(); // ^^
  advance (it2,6);            // ^                 ^
  ++it1;                      //    ^              ^

  it1 = mylist.erase (it1);   // 10 30 40 50 60 70 80 90
                              //    ^           ^

  it2 = mylist.erase (it2);   // 10 30 40 50 60 80 90
                              //    ^           ^

  ++it1;                      //       ^        ^
  --it2;                      //       ^     ^

  mylist.erase (it1,it2);     // 10 30 60 80 90
                              //        ^

  std::cout << "mylist contains:";
  for (it1=mylist.begin(); it1!=mylist.end(); ++it1)
    std::cout << ' ' << *it1;
  std::cout << '\n';

  return 0;
}

2.5.5 clear

2.6  opeations

std::list 提供了一些有用的成员函数,允许执行各种操作,如元素的合并、移除、排序和倒序。下面是这些函数的简要说明和使用示例:

splice: 将元素从一个列表转移到另一个列表,可以转移整个列表、一个单独的元素或一个元素范围。不会执行任何元素的复制或者移动操作,只是在内部节点之间调整指针。

remove: 从列表中移除所有具有特定值的元素。

remove_if: 根据一个判断条件移除元素。

#include <iostream>
#include <list>
bool ref(const int n)
{
    return n % 2 == 0; 
}

int main()
{
    std::list<int> myList = { 1, 2, 3, 4, 5 };
    myList.remove_if(ref);
    for (auto u : myList)
    {
        std::cout << u << " ";
    }
    return 0;
}

unique: 移除连续并且重复的元素,只保留唯一的元素。

#include <iostream>
#include<list>
using namespace std;
int main()
{
    list<int> lt = {1,5,3,4,5,6,2,3,4,1,5,4,5,6};
    lt.unique();
    for (auto u : lt)
    {
        cout << u << " ";
    }
    cout << endl;
    lt.sort();
    lt.unique();
    for (auto u : lt)
    {
        cout << u << " ";
    }
    return 0;
}

merge: 合并两个已排序的列表,并确保结果列表也是排序的。

sort: 对列表中的元素进行排序。它接受一个比较函数作为参数(可选)。

reverse: 反转列表中元素的顺序。

三、模拟实现: 

 3.1基本框架:

namespace moon
{
	template<class T>
	struct __list_node
	{
		T _val;
		__list_node<T>* prev;
		__list_node<T>* next;

		__list_node(const T& x=T())
			:_val(x)
			,prev(nullptr)
			,next(nullptr)
		{}
	};

	template<class T>
	class list
	{
		typedef __list_node<T> Node;
	public:

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

这段代码实现了一个简单双向链表的基础结构。让我们分两部分来解释这个代码: 

3.2 list的基本函数:

🔥list()

list()
{
	_head = new Node;
	_head->prev = _head;
	_head->next = _head;
	_size = 0;
}

🔥尾插 push_back()

void push_back(const T& x)
{
	Node* NewNode = new Node(x);
	Node* end = _head->prev;
	end->next = NewNode;
	NewNode->prev = end;
	_head->prev = NewNode;
	NewNode->next = _head;
	_size++;
}

我们完成了添加元素的基本操作,那么我们如何遍历它呢?

我们需要用迭代器来遍历,这就是我们本篇文章的重点,迭代器的模拟实现。

3.3迭代器的封装和实现: 

1. 链表是随机存储的,让原生指针++,是不会跳到下一个节点。应该对++进行运算符重载。

2. 对原生指针进行解引用,得不到我们需要的节点中的_val。

所以我们需要对迭代器进行封装。 

	template<class T>
	struct __list_iterator
	{
		trpedef __list_node<T> Node;

		//成员变量
		Node* _PtrNode;

		__list_iterator(Node* node)
			:_PtrNode(node)
		{}
	};

注意:我们的迭代器是在list类中访问的: 

我们应该在list类中实现嵌套,对__list_node<T>  typedef

list<int>::iterator it = lt.begin(); 这一行涉及到了所谓的嵌套类型或者内嵌类型

        在C++中,当一个类型(比如 __list_iterator<T>)是在另一个类型的作用域内部定义的(比如 list<T>)时,这个类型被称为嵌套类型。嵌套类型通常用于与外部类型紧密相关联的概念,例如迭代器、节点或其他辅助类。

        这里的 iterator 是 list 类的嵌套类型的别名:

template<class T>
class list {
public:  
    typedef __list_iterator<T> iterator;
};

        所以当我们在类外部引用它时,我们需要使用类的名称(在这个例子中是 list<int>),后跟两个冒号来限定作用域,然后是别名 iterator。因此 list<int>::iterator 指的是 __list_iterator<int>,它是链接到特定的 list 实例化类型的迭代器类型

list<int>::iterator it1=lt.begin();

vector<int>::iterator it2=v.begin();

string::iterator it3=str.begin();

 迭代器就是一个节点的指针,我们这个类的成员就是_PtrNode(节点指针)

	template<class T>
	struct __list_iterator
	{
		trpedef __list_node<T> Node;

		//成员变量
		Node* _PtrNode;

		__list_iterator(Node* node)
			:_PtrNode(node)
		{}
	};

迭代器与list的联系: 

我们还需要在list类中给__list_iterator类提供两个接口,lt.begin() 和lt.end()

	template<class T>
	class list
	{
		typedef __list_node<T> Node;
		typedef __list_iterator<T> iterator;
	public:
		list()
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
			_size = 0;
		}

		iterator begin()
		{
			return _head->next;
		}
		iterator end()
		{
			return _head;
		}

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

 回到最初的问题,实现迭代器的++和*等操作:

🔥operator++()和operator--()

     这里的++/--,改变指针的位置,挪到下一个/上一个节点。

前置++:

		self& operator++()
		{
			_PtrNode = _PtrNode->next;//节点的指针
			return  *this; // 迭代器
		}

后置++:

		self& operator++(int)
		{
			self tmp(*this);
			_PtrNode=_PtrNode->next;
			return tmp;
		}

 前置--:

		self& operator--()
		{
			_PtrNode = _PtrNode->prev;//节点的指针
			return  *this; // 迭代器
		}

后置--:

		self& operator--(int)
		{
			self tmp(*this);
			_PtrNode=_PtrNode->prev;
			return tmp;
		}

 🔥operator*()

T& operator*()
{
	return _PtrNode->_val;
}

  🔥operator!=()

bool operator!=(self& lt)  //it!=lt.end()
{
	return _PtrNode != lt._PtrNode;
}

3.4 list函数的完善: 

 又了迭代器,我们就可以完善list函数了。

 🔥insert()

iterator insert(iterator pos,const T& val)
{
	Node* newnode = new Node(val);
    //pos是__list_iterator类的一个实例化对象,pos._PtrNode是去取对象中的成员
	Node* cur = pos._PtrNode;
	Node* prev = cur->prev;
	// prev newnode cur
	prev->next = newnode;
	newnode->prev = prev;
	cur->prev = newnode;
	newnode->next = cur;
    _size++;
	return newnode;
}

🔥erase()

iterator erase(iterator pos)
{
	Node* cur = pos._PtrNode;
	Node* prev = cur->prev;
	Node* next = cur->next;
	prev->next = next;
	next->prev = prev;
	delete(cur);
	_size--;
	return next;  //erase函数返回的是下一个节点的迭代器
    //同样,这里包括隐式类型转换
}

 🔥拷贝构造

list(const list<T>& lt)//这个函数需要先完成const迭代器才行,const迭代器后面会有模拟实现
{
	_head = new Node;
    _head->_next = _head;
    _head->_prev = _head;
    _size = 0;

	for (auto e : lt)  //通过const迭代器实现
	{
		push_back(e);
	}
}

 🔥赋值重载

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

// lt3 = lt1
list<int>& operator=(list<int> lt)  //自定义类型传参,调用拷贝构造
{
	swap(lt);  //交换头节点和_size
	return *this;  
    //出了函数,lt会去调用析构函数,顺便把一开始*this中的数据清除
}

🔥头尾删插

void push_back(const T& val)
{
	insert(end(), val);
}
void  push_front(const T& val)
{
	insert(begin(), val);
}
void pop_back()
{
	erase(--end());  //end()返回的是带头节点
}
void pop_front()
{
	erase(begin());
}

 🔥与_size相关的函数

//返回_size的大小
size_t size()
{
	return _size;
}

//判断是否为空
bool empty()
{
	return _size == 0;
}

🔥链表销毁

void clear()
{
	iterator it = begin();
	while (it != end())
	{
		it = erase(it); //_size在erase函数中会减小
	}
}
~list()
{
	clear();
	delete _head;
	_head = nullptr;
}

 3.5 进一步完善迭代器:

对于下面的这种类

 struct A
 {
     int _a1;
     int _a2;

     A(int a1 = 0, int a2 = 0)
         :_a1(a1)
         , _a2(a2)
     {}
 };

如果list存的是上面的自定义类型呢?

插入有以下几种方法:

void test_list2()
{
    list<A> lt;
    A aa1(1, 1);
    A aa2 = { 1, 1 };
    lt.push_back(aa1);
    lt.push_back(aa2);
    lt.push_back(A(2, 2));
    lt.push_back({ 3, 3 });
    lt.push_back({ 4, 4 });  
}

上面代码使用不同方式来创建和插入 A 类型的对象到自定义的 list 容器中。下面是每种方式的详细说明以及它们所涉及的概念:

有名对象的直接插入:

这里,首先创建了一个命名对象 aa1,使用了 A 的构造函数 A(int a1, int a2) 并为其提供了两个参数。然后,你将 aa1 作为参数传递给 lt.push_back() 函数。在这种情况下,aa1 是有名对象(也就是说,它有一个名称),并且 push_back 函数接受到的是 aa1 的一个副本

多参数隐式类型转换:

aa2 通过列表初始化的方式被创建。这里的列表初始化允许直接用花括号 {} 来初始化对象。C++11 引入的列表初始化特性可以用来初始化任何对象,包括具有构造函数的对象。创建了 aa2 有名对象并将其插入到列表中

通过构造函数创建匿名对象并插入:

在这里,没有给新创建的 A 对象一个名字,因此它是一个匿名对象(也称作临时对象)。这个匿名的 A 对象是通过调用它的构造函数来直接初始化的,并立即被传递到 push_back 函数中。

通过隐式类型转换创建匿名对象并插入:

与第三种方式类似,创隐式类型转换建了一个匿名的 A 对象,但这次是通过。初始化时没有使用相应类型的构造函数,而是依赖编译器生成的代码来创建一个具有给定初始化列表的对象,并将其传递给 push_back 函数。

在所有这些情况中,实际插入到 list 容器中的都是 A

现在我们来进行遍历:

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

 A是自定义类型,不支持留插入,我们解引用得到的_data是A的对象

这里数据是公有的,解引用得到的可以通过.访问符进行访问

这种访问方式相当于这种形式:

这种指针访问行为十分复杂,我们可以重载一个函数使实现这种访问方式:

在迭代器中重载->运算符

我们就可以这样访问:

实际上它的访问方式如下:

注意:

这里隐藏了一个箭头,一个是重载,一个是原生指针的访问操作

实际上,并不需要在代码中写两次箭头。这是因为在 C++ 中,operator-> 有一个特殊的规则

这是如何工作的:

1.  如果有一个用户自定义类型的对象(比如迭代器)it,并且我们调用 it->member,编译器会查找这个类型是否有 operator->
2.  如果这个类型有一个 operator-> 的重载,编译器就调用 it.operator->()
3.  it.operator->() 应该返回一个指向对象的指针,这个对象有一个我们尝试访问的 member 成员
4.  编译器取得这个指针,并继续访问 member

因此,我们不需要手动写成 it->->member;只需写 it->member 即可。编译器会自动将其 “转换” 为 it.operator->()->member

在 ListIterator 示例里,it->_a1 意味着:

1.  调用 it.operator->() 拿到 ListNode 中 _data 成员的地址(这是一个 A 类型的对象)。
2.  使用返回的指针来访问 A 对象的 _a1 成员。

const迭代器

我们上面写的迭代器对于const对象是无法编译成功的,const不能调用非const成员函数

对于const类迭代器,我们需要在list类里面重新增加重载

typedef _const__list_iterator<T> const_iterator;

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

const_iterator end() const
{
    return _head;
}

1.  这里的const版本不是对普通迭代器进行const修饰。(想象当我们使用const修饰指针,指针不能移动,指针指向的内容可以修改,不符合我们的预期)

2.  const迭代器是一个重新定义的类型,本身可以修改,指向的内容不可以修改

方法一:单独再实现一个const_iterator类

	template<class T>
	struct _const__list_iterator
	{
		typedef __list_node<T> Node;
		typedef _const__list_iterator<T> self;
		//成员变量
		Node* _PtrNode;

		_const__list_iterator(Node* x)
			:_PtrNode(x)
		{}
		self& operator++()
		{
			_PtrNode = _PtrNode->next;//节点的指针
			return  *this; // 迭代器
		}
		self& operator++(int)
		{
			self tmp(*this);
			_PtrNode = _PtrNode->next;
			return tmp;
		}
		self& operator--()
		{
			_PtrNode = _PtrNode->prev;//节点的指针
			return  *this; // 迭代器
		}
		self& operator--(int)
		{
			self tmp(*this);
			_PtrNode = _PtrNode->prev;
			return tmp;
		}
		const T& operator*()
		{
			return _PtrNode->_val;
		}
		bool operator!=(const self& it)  //it!=lt.end()
		{
			return _PtrNode != it._PtrNode;
		}
		const T* operator->()
		{
			return &_PtrNode->_val;
		}
	};

 

 合并两中迭代器:

	template<class T,class Ref,class Ptr>
	struct __list_iterator
	{
		typedef __list_node<T> Node;
		typedef __list_iterator<T,Ref,Ptr> self;
		//成员变量
		Node* _PtrNode;

		__list_iterator(Node* x)
			:_PtrNode(x)
		{}
		Ref operator*()
		{
			return _PtrNode->_val;
		}
		Ptr operator->()
		{
			return &_PtrNode->_val;
		}
		self& operator++()
		{
			_PtrNode = _PtrNode->next;//节点的指针
			return  *this; // 迭代器
		}
		self& operator++(int)
		{
			self tmp(*this);
			_PtrNode=_PtrNode->next;
			return tmp;
		}
		self& operator--()
		{
			_PtrNode = _PtrNode->prev;//节点的指针
			return  *this; // 迭代器
		}
		self& operator--(int)
		{
			self tmp(*this);
			_PtrNode = _PtrNode->prev;
			return tmp;
		}

		bool operator!=(const self& it)  //it!=lt.end()
		{
			return _PtrNode != it._PtrNode;
		}
		
	};

 我们只提取不同的部分,其他部分与原来相同

Ref代表引用,Ptr代表指针

让我们来看一下这个合并后的迭代器的模板参数:

  • T:列表节点存储的数据类型

  • Ref:通过迭代器访问数据时的返回类型,可以是T&或者const T&。

  • Ptr:通过迭代器访问数据的指针类型,可以是T*或者const 

这样,我们可以创建一个常量迭代器,为RefPtr参数指定常量类型,例如:

__list_iterator<T, const T&, const T*> const_iterator;

对于非常量迭代器,就简单地传递非常量类型的引用和指针: 

__list_iterator<T, T&, T*> iterator;

list类中,我们需要相应地声明两种类型的迭代器:

	template<class T>
	class list
	{
	public:
		typedef __list_node<T> Node;
		typedef __list_iterator<T,T&,T*> iterator;
		typedef __list_iterator<T,const T&,const T*> const_iterator;
		list()
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
			_size = 0;
		}
		iterator begin()
		{
			return _head->next;
		}
		iterator end()
		{
			return _head;
		}
		const_iterator begin() const
		{
			return _head->next;
		}
		const_iterator end() const
		{
			return _head;
		}
		iterator insert(iterator pos,const T& val)
		{
			Node* newnode = new Node(val);
			Node* cur = pos._PtrNode;//pos是__list_iterator类的一个实例化对象,pos._PtrNode是去取对象中的成员
			Node* prev = cur->prev;
			// prev newnode cur
			prev->next = newnode;
			newnode->prev = prev;
			cur->prev = newnode;
			newnode->next = cur;
			_size++;
			return newnode;
		}
		iterator erase(iterator pos)
		{
			Node* cur = pos._PtrNode;
			Node* prev = cur->prev;
			Node* next = cur->next;
			prev->next = next;
			next->prev = prev;
			delete(cur);
			_size--;
			return next;
		}
		void push_back(const T& val)
		{
			insert(end(), val);
		}
		void  push_front(const T& val)
		{
			insert(begin(), val);
		}
		void pop_back()
		{
			erase(--end());
		}
		void pop_front()
		{
			erase(begin());
		}
		size_t size()
		{
			return _size;
		}
		bool empty()
		{
			return _size == 0;
		}
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it); //_size在erase函数中会减小
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

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

list类中的其他成员函数像beginend需要按照是否接收常量类型来适配这两种迭代器。 

 模拟实现list的源码,仅供参考,纯手打的代码,可能会有bug,还请各位大佬批评指正。

namespace moon
{
	template<class T>
	struct __list_node
	{
		T _val;
		__list_node<T>* prev;
		__list_node<T>* next;

		__list_node(const T& x=T())
			:_val(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* _PtrNode;

		__list_iterator(Node* x)
			:_PtrNode(x)
		{}
		Ref operator*()
		{
			return _PtrNode->_val;
		}
		Ptr operator->()
		{
			return &_PtrNode->_val;
		}
		self& operator++()
		{
			_PtrNode = _PtrNode->next;//节点的指针
			return  *this; // 迭代器
		}
		self& operator++(int)
		{
			self tmp(*this);
			_PtrNode=_PtrNode->next;
			return tmp;
		}
		self& operator--()
		{
			_PtrNode = _PtrNode->prev;//节点的指针
			return  *this; // 迭代器
		}
		self& operator--(int)
		{
			self tmp(*this);
			_PtrNode = _PtrNode->prev;
			return tmp;
		}

		bool operator!=(const self& it)  //it!=lt.end()
		{
			return _PtrNode != it._PtrNode;
		}
		
	};

	template<class T>
	class list
	{
	public:
		typedef __list_node<T> Node;
		typedef __list_iterator<T,T&,T*> iterator;
		typedef __list_iterator<T,const T&,const T*> const_iterator;
		list()
		{
			_head = new Node;
			_head->prev = _head;
			_head->next = _head;
			_size = 0;
		}
		iterator begin()
		{
			return _head->next;
		}
		iterator end()
		{
			return _head;
		}
		const_iterator begin() const
		{
			return _head->next;
		}
		const_iterator end() const
		{
			return _head;
		}
		iterator insert(iterator pos,const T& val)
		{
			Node* newnode = new Node(val);
			Node* cur = pos._PtrNode;//pos是__list_iterator类的一个实例化对象,pos._PtrNode是去取对象中的成员
			Node* prev = cur->prev;
			// prev newnode cur
			prev->next = newnode;
			newnode->prev = prev;
			cur->prev = newnode;
			newnode->next = cur;
			_size++;
			return newnode;
		}
		iterator erase(iterator pos)
		{
			Node* cur = pos._PtrNode;
			Node* prev = cur->prev;
			Node* next = cur->next;
			prev->next = next;
			next->prev = prev;
			delete(cur);
			_size--;
			return next;
		}
		void push_back(const T& val)
		{
			insert(end(), val);
		}
		void  push_front(const T& val)
		{
			insert(begin(), val);
		}
		void pop_back()
		{
			erase(--end());
		}
		void pop_front()
		{
			erase(begin());
		}
		size_t size()
		{
			return _size;
		}
		bool empty()
		{
			return _size == 0;
		}
		void clear()
		{
			iterator it = begin();
			while (it != end())
			{
				it = erase(it); //_size在erase函数中会减小
			}
		}
		~list()
		{
			clear();
			delete _head;
			_head = nullptr;
		}

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

 

 

 

 

 

举报

相关推荐

0 条评论