STL标准模板库——list模拟实现

目录

一,关于list

二,list模拟实现

2.1 list节点

2.2 list的迭代器类

2.3 list基本框架

 2.4 构造和初始化

 2.5 拷贝和赋值

 2.6 插入操作函数

2.6.1 insert()

2.6.2 push_back()

2.6.3 push_front()

 2.7 删除操作函数

2.7.1 erase()

2.7.2 pop_back()

2.7.3 pop_front() 

 2.8 析构函数

三,完整代码

3.1 list模拟实现

3.2 测试代码


 

一,关于list

相较于vector线性空间,list就显得复杂许多,它的好处是每次插入或删除一个元素,就配置或释放一个空间,list对于空间的运用有绝对的精准,一点也不浪费。而且,对于任何位置的元素插入或删除,list的时间复杂度永远都是常数

list和vector是两个最常被使用的容器,什么十几下最适合使用哪一种容器,必须视元素的多寡,元素的构造复杂度,元素存取行为的特性而定。

二,list模拟实现

2.1 list节点

//节点
template<class T>
struct list_node
{
	list_node(const T& x = T())//T()全缺省
		:_data(x)
		, _next(nullptr)
		, _prev(nullptr)
	{}
	list_node<T>* _next;
	list_node<T>* _prev;
    T _data;
};

2.2 list的迭代器类

 关于list迭代器有以下几个需要重视的点:

list不能再像vector那样一样以普通指针作为迭代器,因为其节点不保证在储存空间中连续存在。list迭代器必须又能力指向list的节点,并有能力进行正确的递增,递减,取值,成员存取等操作。所谓“list迭代器正确的递增,递减,取值,成员取用”操作是指,递增时指向下一个节点,递减时指向上一个节点,取值时取的是节点的数据值,成员取用时取用的是节点的成员。

由于STL库里的list是一个双向链表(double linked_list),迭代器必须具备前移,后移的能力,所以list提供的是 Bidirectional Iterator(双向迭代器)。

list有一个重要性质:插入操作,删除操作和接合操作都不会造成原有迭代器失效,这在vector中是无法做到的,因为vector的插入操作可能会扩容导致记忆体重新配置,导致原有额迭代器全部失效。

//库里的代码
// typedef __list_iterator<T, T&, T*>             iterator;
// typedef __list_iterator<T, const T&, const T*> const_iterator;

//List的迭代器类 -- 像指针一样的类
template<class T, class Ref, class Ptr>//后面两个参数是用来控制迭代器解引用的行为
struct __list_iterator
{
    typedef ListNode<T> Node;
    typedef __list_iterator<T, Ref, Ptr> iterator;
public:
    Node* _node;
    __list_iterator(Node* node)
        :_node(node)
    {}

    bool operator!=(const iterator& it)const
    {
        return _node != it._node;//前面那个是this->_node
    }

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

    //*it会转化成it.operator*(),并且可实现修改
    //const T& operator*()
    
    //const T& operator*()
    //T& operator*()
    Ref operator*()
    {
        return _node->_data;
    }

    //T* operator->()
    Ptr operator->()
    {
        return &(operator*());
    }
    // ++it
    iterator& operator++()
    {
        _node = _node->_next;
        return *this;
    }
    // it++
    iterator operator++(int)
    {
        iterator tmp(*this);
        _node = _node->_next;
        return tmp;
    }
    // --it
    iterator& operator--()
    {
        _node = _node->_prev;
        return *this;
    }
    // it--
    iterator operator--(int)
    {
        iterator tmp(*this);
        _node = _node->_prev;
        return tmp;
    }
};

2.3 list基本框架

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;

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

	const_iterator end()const
	{
		return const_iterator(_head);
	}
	iterator begin()
	{
		return iterator(_head->_next);
	}
	iterator end()
	{
		return iterator(_head);
	}
private:
	Node* _head;//定义哨兵
};

 2.4 构造和初始化

//构造和初始化
void empty_init()
{
	// 创建并初始化哨兵位头结点
	_head = new Node;
	_head->_next = _head;
	_head->_prev = _head;
}
//这里用模板,就是传什么就可以拷贝什么,比如list里面不是int,而是string或者vector
template <class InputIterator>
list(InputIterator first, InputIterator last)//迭代器区间初始化
{
	empty_init();
	while (first != last)
	{
		push_back(*first);
    	++first;
	}
}

//构造,带头双向循环链表
list()
{
	empty_init();
}

 2.5 拷贝和赋值

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

// lt2(lt1) -- 现代写法
list(const list<T>& lt)
{
	empty_init();
	list<T> tmp(lt.begin(), lt.end());//迭代器区间构造tmp
	swap(tmp);
}

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

 2.6 插入操作函数

2.6.1 insert()

iterator insert(iterator pos, const T& x)
{
	Node* cur = pos._node;       //创造pos位置的节点对象
	Node* prev = cur->_prev;     //保存上一个节点的指针
	Node* newnode = new Node(x); //造出新节点

	// 位置关系 prev     newnode      cur
	prev->_next = newnode;
	newnode->_prev = prev;
	newnode->_next = cur;
	cur->_prev = newnode;

	return iterator(newnode);//返回新节点位置的迭代器
}

2.6.2 push_back()

void push_back(const T& x)
{
	//Node* tail = _head->_prev;
	//Node* newnode = new Node(x);
	目前位置关系_head      tail     newnode
	//tail->_next = newnode;
	//newnode->_next = _head;
	//_head->_prev = newnode;
	insert(end(), x);
}

2.6.3 push_front()

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

 2.7 删除操作函数

2.7.1 erase()

iterator erase(iterator pos)
{
	assert(pos != end());//不能把哨兵位删了

	Node* cur = pos._node;
	Node* prev = cur->_prev;
	Node* next = cur->_next;

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

	return iterator(next);//由于迭代器失效的问题,删除后返回下一个位置的迭代器
}

2.7.2 pop_back()

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

2.7.3 pop_front() 

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

 2.8 析构函数

void clear()
{
	iterator it = begin();
	while (it != end())
	{
		it = erase(it);//erase后it失效了,但是会返回下一个位置的迭代器,我们自己实现的有
	}
}

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

三,完整代码

3.1 list模拟实现

#include <assert.h>
#include<list>
//节点
template<class T>
struct list_node
{
	

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

	T _data;
	list_node<T>* _next;
	list_node<T>* _prev;
};

//库里的代码
// typedef __list_iterator<T, T&, T*>             iterator;
// typedef __list_iterator<T, const T&, const T*> const_iterator;

//List的迭代器类 -- 像指针一样的类
template<class T, class Ref, class Ptr>//后面两个参数是用来控制迭代器解引用的行为
struct __list_iterator
{
    typedef ListNode<T> Node;
    typedef __list_iterator<T, Ref, Ptr> iterator;
public:
    Node* _node;
    __list_iterator(Node* node)
        :_node(node)
    {}

    bool operator!=(const iterator& it)const
    {
        return _node != it._node;//前面那个是this->_node
    }

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

    //*it会转化成it.operator*(),并且可实现修改
    //const T& operator*()
    
    //const T& operator*()
    //T& operator*()
    Ref operator*()
    {
        return _node->_data;
    }

    //T* operator->()
    Ptr operator->()
    {
        return &(operator*());
    }
    // ++it
    iterator& operator++()
    {
        _node = _node->_next;
        return *this;
    }
    // it++
    iterator operator++(int)
    {
        iterator tmp(*this);
        _node = _node->_next;
        return tmp;
    }
    // --it
    iterator& operator--()
    {
        _node = _node->_prev;
        return *this;
    }
    // it--
    iterator operator--(int)
    {
        iterator tmp(*this);
        _node = _node->_prev;
        return tmp;
    }
};

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;

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

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

	void empty_init()
	{
		// 创建并初始化哨兵位头结点
		_head = new Node;
		_head->_next = _head;
		_head->_prev = _head;
	}

	//构造和初始化
	template <class InputIterator>
    //这里用模板,就是传什么就可以拷贝什么,比如list里面不是int,而是string或者vector
	list(InputIterator first, InputIterator last)
	{
		empty_init();

		while (first != last)
		{
			push_back(*first);
			++first;
		}
	}

	//构造,带头双向循环链表
	list()
	{
		empty_init();
	}
	void swap(list<T>& x)
	{
		std::swap(_head, x._head);
	}

	// lt2(lt1) -- 现代写法
	list(const list<T>& lt)
	{
		empty_init();
		list<T> tmp(lt.begin(), lt.end());//迭代器区间构造tmp
		swap(tmp);
	}

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

	iterator insert(iterator pos, const T& x)
	{
		Node* cur = pos._node;       //创造pos位置的节点对象
		Node* prev = cur->_prev;     //保存上一个节点的指针
		Node* newnode = new Node(x); //造出新节点

		// 位置关系 prev     newnode      cur
		prev->_next = newnode;
		newnode->_prev = prev;
		newnode->_next = cur;
		cur->_prev = newnode;

		return iterator(newnode);//返回新节点位置的迭代器
	}

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

	void clear()//库里的clear只清数据不清头结点
	{
		iterator it = begin();
		while (it != end())
		{
			it = erase(it);//erase后it失效了,但是会返回下一个位置的迭代器,我们自己实现的有
		}
	}

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

	iterator erase(iterator pos)
	{
		assert(pos != end());//不能把哨兵位删了

		Node* cur = pos._node;
		Node* prev = cur->_prev;
		Node* next = cur->_next;

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

		return iterator(next);//由于迭代器失效的问题,删除后返回下一个位置的迭代器
	}

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

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

private:
	Node* _head;//定义哨兵
};

3.2 测试代码

void test_list1()
{
	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;

	it = lt.begin();
	while (it != lt.end())
	{
		*it *= 2;
		++it;
	}
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}
struct Pos
{
	int _a1;
	int _a2;

	Pos(int a1 = 0, int a2 = 0)
		:_a1(a1)
		, _a2(a2)
	{}
};
//->
void test_list2()
{
	int x = 10;
	int* p1 = &x;
	cout << *p1 << endl;

	Pos aa;
	Pos* p2 = &aa;
	p2->_a1;
	p2->_a2;

	list<Pos> lt;
	lt.push_back(Pos(10, 20));
	lt.push_back(Pos(10, 21));

	list<Pos>::iterator it = lt.begin();
	while (it != lt.end())
	{
		//cout << (*it)._a1 << " " << (*it)._a2 << endl;//这个访问方式不爽,可以直接用箭头去访问
		cout << it->_a1 << ":" << it->_a2 << endl;
		//->咋调用的呢?//看板书
		++it;
	}
	cout << endl;
}
void Func(const list<int>& l)//用了&就可以加const
{
	//list<int>::iterator it = l.begin();//报错,权限放大
	list<int>::const_iterator it = l.begin();//const迭代器
	while (it != l.end())
	{
		//*it = 10;const不能修改

		cout << *it << " ";
		++it;
	}
	cout << endl;
}
void test_list3()
{
	list<int> lt;
	lt.push_back(1);
	lt.push_back(2);
	lt.push_back(3);
	lt.push_back(4);
	lt.push_back(5);

	Func(lt);
}
void test_list4()
{
	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;
	lt.push_front(10);
	lt.push_front(20);
	lt.push_front(30);
	lt.push_front(40);
	lt.pop_back();
	lt.pop_back();
	lt.pop_front();
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;

	auto pos = find(lt.begin(), lt.end(), 3);
	if (pos != lt.end())
	{
		// pos是否会失效?不会
		lt.insert(pos, 30);
		//lt.insert(pos, 30);
		*pos *= 100;
	}
	for (auto e : lt)
	{
		cout << e << " ";
	}
	cout << endl;
}
void test_list5()
{
	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> copy = lt;
	for (auto& e : lt)
	{
		e *= 2;
	}
	cout << endl;

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

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

	//lt.clear();

	list<int> lt1;
	lt1.push_back(10);
	lt1.push_back(20);
	lt1.push_back(30);

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

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

void test_list6()
{
	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> lt2(lt);
}

  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值